【发布时间】:2017-01-18 18:41:15
【问题描述】:
我目前正在使用 Unity 容器在现有 ASP.NET Web API 项目中实现依赖注入。
我已经设法通过配置依赖解析器将我的服务类注入到我的 API 控制器中。
但对于控制器功能,我必须使用数据传输对象 (DTO)。
在那个对象中,我找不到如何使用我的模型合同。
这是 Web API 控制器方法:
[HttpPost]
[Route("api/application/save")]
public IHttpActionResult SaveApplication(ApplicationUpdateDTO applicationUpdate)
{
// Inner code calling service methods expecting IApplication and
// collections of ITag as parameters.
}
这是DTO定义:
public class ApplicationUpdateDTO
{
public IApplication Application { get; set; }
public IEnumerable<int> DeletedTagIds { get; set; }
public IEnumerable<ITag> AddedTags { get; set; }
public IEnumerable<int> DeletedPlatformIds { get; set; }
public IEnumerable<ITag> AddedPlatforms { get; set; }
}
结果是DTO本身被初始化了,但不是所有null的属性。
我理解为什么不能设置属性:接口不能被实例化,并且它不知道要使用哪些类。但是我的 Unity 容器可以,这要归功于注册。
- 是否可以以某种方式使用此“链接”来初始化 DTO 属性?
- 有更好的方法吗?
注意事项:
- 如果我在 DTO 中使用我的接口实现,它显然可以正常工作。
- 控制器方法接收一个与我的 DTO 相同的 JSON 对象。
编辑
我还通过引用this post尝试了ModelBinder的实现。
但是对于关于ValueProviderResult 的行,我得到了null 值。
为方便起见,以下是 Todd 在另一个问题中的回答:
public class CreateSomethingModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
string key = bindingContext.ModelName;
ValueProviderResult val = bindingContext.ValueProvider.GetValue(key);
if (val != null)
{
string s = val.AttemptedValue as string;
if (s != null)
{
return new CreateSomething(){Title = s; UserId = new Guid(ControllerContext.HttpContext.Request.Headers["userId"]);}
}
}
return null;
}
}
我从问题的回答中得到的一个小区别是使用 System.Web.Http.ModelBinding.IModelBinder 而不是 MVC。
根据要求,这里是我的界面的摘录。
IApplication 界面:
public interface IApplication
{
/// <summary>
/// Identifier of the application.
/// </summary>
int Id { get; set; }
/// <summary>
/// Name of the application.
/// </summary>
string Name { get; set; }
/// <summary>
/// Version of the application.
/// </summary>
string Version { get; set; }
/// <summary>
/// Tags associated to the application.
/// </summary>
ICollection<ITag> Tags { get; }
}
ITag 界面:
public interface ITag
{
/// <summary>
/// Identifier of the tag.
/// </summary>
int Id { get; set; }
/// <summary>
/// Identifier of the application to which the tag is linked.
/// </summary>
int ApplicationId { get; set; }
/// <summary>
/// Value of the tag.
/// </summary>
string Value { get; set; }
}
JSON 示例:
{
"marketApplication": {
"Id": 20,
"Name": "MyApplication",
"Version": "2.0"
},
"deletedTagIds": [],
"addedTags": [
{
"Id": 0,
"Value": "NewTag"
}
],
"deletedProgramIds": [],
"addedPrograms": [
{
"Id": 0,
"Name": "x86"
}
]
}
【问题讨论】:
-
创建自定义模型绑定器以在绑定模型时解析合同实现。在那里您提取与您的属性相关的段并反序列化/解析然后分配给属性
-
@Nkosi 我有效地尝试在this topic 的帮助下创建一个ModelBinder,但我为
ValueProviderResult(ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(key);) 检索了一个null。我虽然当时这不是我正在寻找的答案。 -
举例说明接口、实现和发送的JSON
-
你能解释一下为什么你的 DTO 使用接口而不是具体的类吗?接口的使用通常仅在需要抽象某些行为时才有用。抽象数据本身通常根本没有用(因为它只是数据)。从这个角度来看,直接使用具体类更有意义,并且可以通过 Web API 开箱即用地绑定模型。
-
创建一个自定义模型绑定器,用于查找所请求接口的类型并对其进行水合。
标签: c# asp.net-web-api dependency-injection unity-container