以下代码在asp.net web API
中工作正常但在Asp.net核心中不起作用。
端点api/devices?query={"deviceName":"example"}
[HttpGet]
public Device ([FromUri] string deviceName)
{
var device = context.Computers.Where(x => x.deviceName == deviceName);
return device;
}
[FromUri]
属性不存在asp.net
核心网API
,我尝试使用以下内容,但没有成功。
[HttpGet]
public Device Get([FromQuery] string deviceName)
{
return repo.GetDeviceByName(deviceName);
}
答案 0 :(得分:4)
不幸的是,没有办法像你那样在GET查询中绑定JSON。您正在寻找的是使用自定义模型绑定器告诉ASP.net Core您想要绑定的方式。
首先,您要为JSON对象构建模型。
public class MyCustomModel
{
public string DeviceName { get; set; }
}
接下来,您需要构建模型绑定器。下面给出一个简单的例子,但你显然想要进行其他检查是否可以转换,Try / Catch块等。本质上,模型绑定器告诉ASP.net Core应该如何绑定模型。您可能还遇到了类型的TypeConverters,如何在模型绑定期间将其更改为其他类型。现在让我们使用modelbinders。
public class MyViewModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var jsonString = bindingContext.ActionContext.HttpContext.Request.Query["query"];
MyCustomModel result = JsonConvert.DeserializeObject<MyCustomModel>(jsonString);
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
所以我们所做的就是获取查询字符串并将其反序列化为我们的模型。
接下来我们建立一个提供者。提供者告诉ASP.net核心使用哪个模型绑定器。在我们的例子中,它很简单,如果模型类型是我们的自定义类型,那么使用我们的自定义绑定器。
public class MyViewModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType == typeof(MyCustomModel))
return new MyViewModelBinder();
return null;
}
}
最后一块拼图。在我们的startup.cs中,我们找到了添加MVC服务的位置,并将模型绑定器插入到列表的前面。这个很重要。如果我们只是将我们的模型绑定器添加到列表中,另一个模型绑定器可能会认为应该使用它(First in first served),所以我们可能永远不会将它变为我们的。所以一定要在开始时插入它。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config => config.ModelBinderProviders.Insert(0, new MyViewModelBinderProvider()));
}
现在我们只创建一个我们读取数据的动作,不需要任何属性。
[HttpGet]
public void Get(MyCustomModel model)
{
}
进一步阅读:
答案 1 :(得分:0)
我提出这个问题是因为我有类似的问题。 在我的场景中,实现 ModelBinderAttribute 更方便:
public class FromUriJsonAttribute : ModelBinderAttribute
{
public FromUriJsonAttribute()
{
BinderType = typeof(JsonBinder);
}
public FromUriJsonAttribute(string paramName)
: this()
{
Name = paramName;
}
}
在@MindingData 回答中需要活页夹:
public class JsonBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
try
{
var name = bindingContext.ModelName;
var json = actionContext.Request.GetQueryNameValuePairs().FirstOrDefault(x => x.Key == name).Value;
var targetType = bindingContext.ModelType;
var model = Newtonsoft.Json.JsonConvert.DeserializeObject(json, targetType);
bindingContext.Model = model;
return true;
}
catch
{
}
return false;
}
}
以及用法:
[Route("{id}/items")]
public Item GetItem(string id, [FromUriJson] Filter filter)
{
//logic
}
或:
[Route("{id}/items")]
public Item GetItem(string id, [FromUriJson("queryStringKey")] Filter filter)
{
//logic
}
如果您只想在某些端点中使用 Json 格式的查询字符串参数和/或不想通过插入新的 IModelBinderProvider 实现来弄乱默认的 IServiceCollection 配置,这会很有用。