是否可以将 & 分隔的无密钥 url 参数提取到 .NET Core 中的操作方法参数中?

Posted

技术标签:

【中文标题】是否可以将 & 分隔的无密钥 url 参数提取到 .NET Core 中的操作方法参数中?【英文标题】:Is it possible to extract ampersand-separated keyless url parameters into action method parameters in .NET Core? 【发布时间】:2021-12-15 23:17:13 【问题描述】:

外部服务正在使用 mysite.com/date/2021&4&12 格式的 URL 调用我的 .NET Core API。我无法控制它如何调用我的 API,所以我必须适应这种 URL 格式。

我可以在我的控制器操作方法中解决这个问题

[HttpGet("date/dateString")]
public Thing GetThingByDate(string dateString)

  //...string manipulation on dateString

但是有没有可能让 .NET Core 来完成这项工作,甚至可以自己编写一些东西以便我可以得到

[HttpGet("date/((some kind of formatting here))")]
public Thing GetThingByDate(int year, int month, int day)


【问题讨论】:

【参考方案1】:

是的,这是可能的。使其可重用的一种方法是为此创建自定义模型和模型绑定器。

首先是我的幼稚控制器实现:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase


    [HttpGet("**slug")]
    public IActionResult Get(MyDateModel slug)
    
        return Ok(slug);
    



[ModelBinder(BinderType = typeof(MyDateModelBinder))]
public class MyDateModel

    public int Year  get; set; 
    public int Month  get; set; 
    public int Day  get; set; 

**slug 是一个包罗万象的属性,因此尚未绑定的所有内容都被放入名为“slug”的变量中。在我们的例子中是“2021&4&12”

我们还使用我们的年、月和日属性创建了一个新视图模型,并将其绑定到我们尚未创建的模型绑定器。

现在所有的魔法都发生了。 Microsoft 在https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-5.0 提供了一个很好的示例作为起点。我们的工作将以此为基础:

public class MyDateModelBinder : IModelBinder

    public Task BindModelAsync(ModelBindingContext bindingContext)
    
        if (bindingContext == null)
        
            throw new ArgumentNullException(nameof(bindingContext));
        

        var modelName = bindingContext.ModelName;

        // Try to fetch the value of the argument by name
        var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);

        if (valueProviderResult == ValueProviderResult.None)
        
            return Task.CompletedTask;
        

        bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);

        var rawValue = valueProviderResult.FirstValue;

        // Check if the argument value is null or empty
        if (string.IsNullOrEmpty(rawValue))
        
            return Task.CompletedTask;
        

        // parse the string to the target value
        try
        
            var values = rawValue.Split("&");
            var model = new MyDateModel
            
                Year = Int32.Parse(values[0]),
                Month = Int32.Parse(values[1]),
                Day = Int32.Parse(values[2]),
            ;

            bindingContext.Result = ModelBindingResult.Success(model);
        
        catch (Exception ex)
        
            bindingContext.ModelState.TryAddModelError(
                modelName, ex.Message);

        
        return Task.CompletedTask;
    


我不会详细说明哪一行会发生什么,因为您可以设置断点并获得一个好的 Eureka! - 时刻你自己。请注意,这种相当幼稚的实现缺少大量的稳健性和错误处理 - 因此,如果您的字符串格式错误或分隔符错误,它将无法正常工作,并且您的错误消息可能不适合客户端。

在我们现在的示例中,我发出了请求 https://localhost:5001/api/values/2021&4&12,它以 JSON 形式返回了以下值:


    "year": 2021,
    "month": 4,
    "day": 12

【讨论】:

以上是关于是否可以将 & 分隔的无密钥 url 参数提取到 .NET Core 中的操作方法参数中?的主要内容,如果未能解决你的问题,请参考以下文章

url编码 - JS & jQuery Notes

get请求时特殊符号处理

URL的编码

请求传参 有特殊符号

记录url 中出现特殊字符该怎么办

url转义