I'm currently implementing dependency injection in an existing ASP.NET Web API project using the Unity container.
I already manage to inject my service classes into my API controller by configuring a dependency resolver.
But for a controller function, I have to use a Data Transfer Object (DTO).
In that object, I can't find how to use my model contracts.
Here is the Web API controller method:
[HttpPost]
[Route("api/application/save")]
public IHttpActionResult SaveApplication(ApplicationUpdateDTO applicationUpdate)
{
// Inner code calling service methods expecting IApplication and
// collections of ITag as parameters.
}
And here is the DTO definition:
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; }
}
As a result, the DTO itself is initialized, but not the properties that are all null
.
I understand why the properties cannot be set : the interfaces cannot be instanciated and it doesn't have any clue of which classes to use for that. But my Unity container does, thanks to the registration.
- Is it possible to use this "link" somehow to initialize the DTO properties?
- Is there a better way do this?
Notes:
- If I use implementations of my interfaces in the DTO, it obviously works fine.
- The controller method receives a JSON object that is identical to my DTO.
edit
I also tried the implementation of a ModelBinder
by referring to this post.
But for the line about the ValueProviderResult
, I got a null
value.
For convenience, here is the response from Todd in the other question:
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;
}
}
The small difference I got from the response of the question, is the usage of the System.Web.Http.ModelBinding.IModelBinder
instead of the MVC one.
As requested, here are exerpts of my interfaces.
The IApplication interface:
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; }
}
The ITag interface:
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; }
}
An example of JSON:
{
"marketApplication": {
"Id": 20,
"Name": "MyApplication",
"Version": "2.0"
},
"deletedTagIds": [],
"addedTags": [
{
"Id": 0,
"Value": "NewTag"
}
],
"deletedProgramIds": [],
"addedPrograms": [
{
"Id": 0,
"Name": "x86"
}
]
}