因为您使用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<T>,...所以它比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&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&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;