I have an object that looks pretty much like this:
public class MyNiceRequest
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string SomeOptionalField { get; set; }
}
And my controller looks like the following, pretty standard still:
public MyNiceResponse Post(MyNiceRequest request) {
...
}
From the front end of the calling application, I want to include more fields than the three specified in the object. These fields are runtime generated (controlled via an admin interface), so I cannot apply them to my request class. However, I've not found a good way to retrieve them in the controller.
I can make my request object (MyNiceRequest
) inherit from Dictionary<string,string>
- then I'll get them all, but they won't be bound to their respective properties on the strongly typed class (seems like the Dictionary is bound before the rest in whatever model binder is used). Plus, more importantly, validation - which is crucial to the application - stops working.
I have seen this question, but it doesn't give me anything as the Request.Content.Read...
-methods give me empty results (since it's already read and bound to a model?).
Let's say I want the following fields from the front end:
FirstName
(should bind to strongly typed, nowhere else)LastName
(should bind to strongly typed, nowhere else)SomeOptionalField
(should bind to strongly typed, nowhere else)RuntimeGenerated1
(should end up in dictionary)RuntimeGenerated2
(should end up in dictionary)I want one of two solutions:
Dictionary<string,string>
, but let the dictionary be bound AFTER the strongly typed properties to let the validation do it's workMyNiceRequest
that could be something like Dictionary<string,string> TheRest { get; set; }
and bind that to the remaining incoming properties somewhere.Rewriting the front end to pass in the runtime generated fields as a separate collection is not an option.
..and can this at all be achieved by reusing/reordering existing stuff, or will I have to write a complete media type formatter and/or model binder from scratch?
HTTP is the default formatting style, provided by the DefaultHttpLogFormatter .
By default, Web API produces XML but if there is need for JSON, given syntax will do it. Open WebApiConfig. cs file in solution and add mentioned line in it as shown in example.
The Web API returns the data on request from the client, and it can be in the format XML or JSON. The MVC architecture is the Model-View-Controller Pattern. It is used for isolating an application to simplify testing and the maintenance of the code of the application.
For application/json
content type, you can use DynamicObject
with WebAPI's default JSON formatter.
public class MyNiceRequest : DynamicObject
{
private Dictionary<string, string> _dynamicMembers = new Dictionary<string, string>();
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string SomeOptionalField { get; set; }
[JsonIgnore]
public Dictionary<string, string> DynamicMembers
{
get { return _dynamicMembers; }
}
public override bool TryGetMember(GetMemberBinder binder, out object value)
{
string stringValue;
var isFound = _dynamicMembers.TryGetValue(binder.Name, out stringValue);
value = stringValue;
return isFound;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (value is string)
{
_dynamicMembers[binder.Name] = (string)value;
return true;
}
return false;
}
}
Edit
If you want the object to be serialized with the same format, implement IDictionary<string, string>
. This is easy, just delegate the interface implementation to _dynamicMembers
This solution doesn't work with the default XML and x-www-form-urlencoded formatters :(
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With