【问题标题】:Pass json string as Route Parameter in .net core razor将 json 字符串作为 .net core razor 中的路由参数传递
【发布时间】:2021-03-05 11:21:29
【问题描述】:

我有一个动作方法,它以数组 [] 作为参数,如下所示

public IActionResult MyAction(string[] data)
{
   -- Further Implementation -- 
   return View(model);
}

在视图方面我使用以下代码,这里我使用路由将数据传递给控制器​​。

 var array = JSON.stringify(cityList); --This is Json String which i wanter to pass 

-- want convert this json String into c# string.  

 window.location.href = "@Url.RouteUrl("PrintWorkAssignement",**Need to pass string**)";

那么有什么方法可以将 json 字符串转换为 C# 字符串,以便我可以将其作为参数发送到控制器?

【问题讨论】:

标签: c# asp.net-core asp.net-mvc-routing


【解决方案1】:

因为您使用Url.RouteUrl,所以我假设您有一个按路由名称定位的操作。这也意味着您需要将路由值传递给类型为string[] 的绑定参数。所以在这种情况下,它是一个复杂的类型。该值不会为您自动转换。您需要一个带有 json 输入(原始)值的自定义 IModelBinder,如下所示:

public class JsonEnumerableBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (typeof(IEnumerable).IsAssignableFrom(bindingContext.ModelType))
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.FieldName).FirstValue;
            if (!string.IsNullOrWhiteSpace(value))
            {
                try
                {
                    var modelType = bindingContext.ModelType == typeof(IEnumerable) ? typeof(List<object>) :
                                    bindingContext.ModelType.IsGenericType &&
                                    bindingContext.ModelType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ?
                                    typeof(List<object>).MakeGenericType(bindingContext.ModelType.GetGenericArguments()[0]) :
                                    bindingContext.ModelType;
                    bindingContext.Result = ModelBindingResult.Success(JsonSerializer.Deserialize(value, modelType));
                }
                catch
                {
                    bindingContext.Result = ModelBindingResult.Failed();
                }
            }
        }
        return Task.CompletedTask;
    }
}

请注意,上面的模型绑定器可以将值绑定到IEnumerable 类型的参数,例如string[]List&lt;T&gt;,...所以它比string[] 的参数类型更通用。

您可以使用IModelBinderProvider全局提供您的自定义模型绑定器。但是在这种情况下,我建议在 ModelBinderAttribute 的帮助下使用显式参数范围绑定,如下所示:

public IActionResult MyAction([ModelBinder(typeof(JsonEnumerableBinder))] string[] data) { ... }

以下是您为Url.RouteUrl 传递值的方式:

//json is the json string you have
window.location.href = "@Url.RouteUrl("PrintWorkAssignement", new { data = json })";

最后有一条关于使用 JSON 作为路径(段)的一部分生成的看起来不好的 URL 的注释。因为正如我所说,您似乎将data 与出现在路由模式中的路由值绑定,如下所示:

[Route("parent/{data}", Name = "PrintWorkAssignement")]
public IActionResult MyAction([ModelBinder(typeof(JsonEnumerableBinder))] string[] data) {...}

这当然会生成丑陋的 URL。因此,在这种情况下,您可能希望使用查询字符串为您的data 绑定值。 json 附加在路径的末尾(作为查询字符串值)看起来更好。要使用查询字符串,只需删除路由模式中的{data} 部分。该值将作为查询字符串附加,您的自定义 IModelBinder 仍然有效。但是,如果将其绑定为查询字符串,您还有另一个选项可以使其工作而无需传递 json 并需要自定义 IModelBinder(如我们在上面应用的那样)。 string[] 可以从一组查询字符串变量中绑定,每个变量都是一个项目,例如 data[0]=abc&amp;data[1]=xyz。这就是您的查询字符串需要的格式(不是 json)(并且您不再需要自定义 IModelBinder)。首先,您需要一个 javascript 函数来将您的数组转换为该格式的值:

//just a simple function target an array of string
//you can build a more complex function (or find somewhere) which targets an object graph
function getQueryString(stringArray, paramName){
   return stringArray.map(function(e,i) { return paramName + "[" + i + "]=" + e;  })
                     .join("&");
}

请注意,在 jQuery 中,您有函数 $.param 应该可以工作,但是对于这种情况(格式化字符串数组),它会以某种方式转换为类似 data[]=abc&amp;data[]=xyz 的格式(缺少索引)。该格式不起作用,并且在服务器端不会为您绑定任何值(至少这是我在asp.net core 2.2 上测试的)。始终包含索引以确保其正常工作。

现在有了这个函数,你可以改用这样的查询字符串:

var queryString = getQueryString(yourStringArray, "data");

//your link built by query string, remember to remove the [ModelBinder(...)] on your action method
window.location.href = "@Url.RouteUrl("PrintWorkAssignement")?" + queryString;

【讨论】:

    【解决方案2】:

    作为查询参数的数组应如下所示:

    www.test.com/api/testaction?data=first&data=second&data=third
    

    请注意,值的名称应与操作方法中的参数名称相同(data

    【讨论】:

      猜你喜欢
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      • 2017-09-09
      • 1970-01-01
      相关资源
      最近更新 更多