Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

RedirectToAction with Non-English Characters in Parameters and Authentication Causes Error #7529

Closed
@busyscout

Description

@busyscout

By default Asp.Net Core encodes non-english characters in view.
Let's create a very simple controller:

public class HomeController : Controller
{
	public IActionResult Index(Parameters param)
	{
		return View(param);
	}

	public IActionResult ToIndex(Parameters param)
	{
		return RedirectToAction("Index", param);
	}

	public class Parameters
	{
		public String Name { get; set; }
	}
}

and a very simple View, which greets a user:

@model TestNonEngLetters.Controllers.HomeController.Parameters
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        Hello, @Model.Name!
    </body>
</html>

If Name contains non-english characters (e.g. Jörn) it gets encoded:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        Hello, J&#xF6;rn!
    </body>
</html>

If we don't want this kind of encoding there is a way to turn it off. We need to add this line of code to Startup.cs:

services.Configure<WebEncoderOptions>(options => options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All));

Now our html becomes pretty good:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Test</title>
    </head>
    <body>
        Hello, Jörn!
    </body>
</html>

Our Startup.cs looks like this:

public class Startup
{
	public void ConfigureServices(IServiceCollection services)
	{
		//services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);

		services.AddMvc();
		services.Configure<WebEncoderOptions>(options => options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All));
	}

	public void Configure(IApplicationBuilder app, IHostingEnvironment env)
	{
		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}

		app.UseMvc(routes =>
		{
			routes.MapRoute(
				name: "default",
				template: "{controller=Home}/{action=Index}/{id?}");
		});
	}
}

Let's invoke our ToIndex action, that must redirect us back to Index:

public IActionResult ToIndex(Parameters param)
{
	return RedirectToAction("Index", param);
}

So we invoke page http://localhost:2616/Home/ToIndex?Name=Jörn and receive expected 302 response with location=/?Name=J%C3%B6rn http header.
Everything works just fine... until we add authentication to our project. See the commented line in Startup.cs?

//services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);

Let's uncomment it and invoke our ToIndex action again.
And what we get?

InvalidOperationException: Invalid non-ASCII or control character in header: 0x00F6

    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.FrameHeaders.ThrowInvalidHeaderCharacter(char ch)
    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.FrameHeaders.ValidateHeaderCharacters(string headerCharacters)
    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.FrameHeaders.ValidateHeaderCharacters(StringValues headerValues)
    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.FrameResponseHeaders.SetValueFast(string key, StringValues value)
    Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.FrameHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(string key, StringValues value)
    Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.Redirect(string location, bool permanent)
    Microsoft.AspNetCore.Mvc.Internal.RedirectToActionResultExecutor.Execute(ActionContext context, RedirectToActionResult result)
    Microsoft.AspNetCore.Mvc.RedirectToActionResult.ExecuteResult(ActionContext context)
    Microsoft.AspNetCore.Mvc.ActionResult.ExecuteResultAsync(ActionContext context)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeResultAsync>d__19.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResultFilterAsync>d__24.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
    System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

it looks like now, when authentication module is in place, asp.net core is not able to set location header correctly.
So, maybe we have chosen the wrong way to deal with encoding of non-english characters or is it a bug in framework itself?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions