如果我们在 Asp.Net Core 中有这样的控制器端点:
[HttpGet("/api/resources/{someParam}")]
public async Task<ActionResult> TestEndpoint([FromRoute] string someParam)
{
string someParamUrlDecoded = HttpUtility.UrlDecode(someParam);
// do stuff with url decoded param...
}
是否有某种方法可以配置
[FromRoute]
解析行为,使其注入 someParam
已经 url 解码的值?
实现您想要做的任何事情的一种方法是创建自定义属性。在该属性内,您基本上可以拦截传入参数并执行您需要的任何操作。
属性定义:
public class DecodeQueryParamAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
string param = context.ActionArguments["param"] as string;
context.ActionArguments["param"] = "Blah"; // this is where your logic is going to sit
base.OnActionExecuting(context);
}
}
在控制器中,您需要使用属性来装饰操作方法,如下所示。路线可以根据您的需要修改。
[HttpGet("/{param}")]
[Attributes.DecodeQueryParamAttribute]
public void Process([FromRoute] string param)
{
// value of param here is 'Blah'
// Action method
}
请注意,当您要将编码字符串作为查询字符串参数传递时,您可能需要检查是否允许双重转义及其含义。
我可以通过添加自定义中间件来更新路由值来实现此目的:
app.Use((context, next) =>
{
if (context.Request.RouteValues.ContainsKey("someParam"))
{
context.Request.RouteValues["someParam"] = HttpUtility.UrlDecode(context.Request.RouteValues["someParam"]?.ToString());
}
return next(context);
});
我已经用这样的约束实现了解决方案:
public class UrlDecodeStringConstraint: IRouteConstraint
{
public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
values[routeKey] = WebUtility.UrlDecode(values[routeKey].ToString());
return true;
}
}
在您的
Startup.cs
课程中:
builder.Services.Configure<RouteOptions>(options => { options.ConstraintMap.Add("UrlDecodeString", typeof(UrlDecodeStringConstraint)); });
在您的控制器中:
[HttpGet("getperson/{personName:UrlDecodeString}")]
public async ValueTask<ActionResult<Person>> GetPerson([FromRoute] string personName)