在 .net core razor 中将 json 字符串作为路由参数传递
Pass json string as Route Parameter in .net core razor
我有一个将数组[]作为参数的操作方法,如下所示
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**)";
So is there any way that i can convert that json string into C# string, so that i can place it as a parameter and send it to controller ?
因为您使用 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>
、...所以它比 [=] 的参数类型更通用17=].
您可以使用 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 })";
最后有一条关于不好看的 URL 生成的注释,其中 JSON 是路径(段)的一部分。因为正如我所说,您似乎将 data
与路由模式中出现的路由值绑定,如下所示:
[Route("parent/{data}", Name = "PrintWorkAssignement")]
public IActionResult MyAction([ModelBinder(typeof(JsonEnumerableBinder))] string[] data) {...}
那当然会产生难看的 URLs。因此,在这种情况下,您可能希望使用查询字符串来绑定 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;
作为查询参数的数组应如下所示:
www.test.com/api/testaction?data=first&data=second&data=third
注意值的名称应与操作方法中的参数名称相同(data
)
我有一个将数组[]作为参数的操作方法,如下所示
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**)";
So is there any way that i can convert that json string into C# string, so that i can place it as a parameter and send it to controller ?
因为您使用 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>
、...所以它比 [=] 的参数类型更通用17=].
您可以使用 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 })";
最后有一条关于不好看的 URL 生成的注释,其中 JSON 是路径(段)的一部分。因为正如我所说,您似乎将 data
与路由模式中出现的路由值绑定,如下所示:
[Route("parent/{data}", Name = "PrintWorkAssignement")]
public IActionResult MyAction([ModelBinder(typeof(JsonEnumerableBinder))] string[] data) {...}
那当然会产生难看的 URLs。因此,在这种情况下,您可能希望使用查询字符串来绑定 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;
作为查询参数的数组应如下所示:
www.test.com/api/testaction?data=first&data=second&data=third
注意值的名称应与操作方法中的参数名称相同(data
)