Is it valid to apply JsonConverter for query string arguments - asp.net-web-api

All,
My team has recently encountered with a roadblock of using JsonConverter with HttpRequest arguments.
My API method definition is as below
[HttpGet]
[GET("Values/Data/{inputString}/{inputDateTime:datetime}")]
public HttpResponseMessage GetResponseForData(string inputString, [JsonConverter(typeof(DateTimeToTicksConverter))] DateTime inputDateTime)
{
// do something here
}
The DateTimeToTicksConverter is to intercept the DateTime attributes and then transform as defined. When this attribute is applied on the attributes of a model it works fine. However when the attribute is defined as in the API above it doesn't intercept during request.
I would like to know if it is valid to expect JsonConverter to intercept the request parameters?
Any help is much appreciated. Thanks

That's not meant to be used there, that attribute is just metada which json.net looks for when serializing a class to JSON, but webapi has no knowledge of it.
You can achieve what you want using a custom httpparameterbinding. You can find more info here http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Related

Web api map request parameter with a hyphen to a Pascal cased complex model property

I am trying to figure out a way to map POSTED form parameters that have hyphens in them to a WEB-API method that takes a complex object.
Some context:
We are using Mailgun to forward a processed email to our own custom Web API Controller method.
Mailgun POSTS to our API and some of the parameters it uses have hyphens in them - for example: body-plain.
My C# complex model will have a property to match in Pascal Case (can't use hyphens in property names)
so if these parameters are generated by Mailgun and posted to our WEB API controller:
from
subject
body-plain
body-stripped
timestamp
and our complex object looks like this:
public class Response{
public string From{get; set;}
public string Subject{get; set;}
public string BodyPlain{get; set;}
public string BodyStripped{get; set;
public int Timestamp{get; set;}
}
Then From, Subject, and Timestamp all map correctly - but BodyPlain and BodyStripped do not - they are null since the model binding can't translate the hyphenated parameters to Camelcase.
Is there a way to do this?
I have seen some posts referring to different ways to achieve this with MVC but we are not using MVC, just strictly WEB API.
You can use the Request object in the controller, which will make the parameters available key/value style.
In the case of Mailgun forwarding (which was the same problem I ran into), the Request.ReadFormAsync() method will expose the IFormCollection, from which you can access the parameters you need via:
IFormCollection.TryGetValue("my-parameter", out StringValues myParameter)
Since the parameters are sent through form submission and not JSON, using [JsonProperty(PropertyName = "my-param")] won't help and you'll have to resort to having your action receiving a parameter of type FormDataCollection and then inside your action you'll map it to your complex object. An alternative is to implement a custom model binder.
In this post there are details about those two options.

Coding to an interface on a Spring Controller method with #RequestMapping

I have a Controller with the following method:
#RequestMapping(method = POST)
public ModelAndView emailRegister(EmailParameter parameters, ModelMap model) {}
Where EmailParameter is an interface. I understand Spring (magically?) maps the incoming HTTP parameters to my object fields by name, and it can't do this as I have declared an Interface.
Is it possible to declare an interface here, if so is there additional config I need somewhere?
I don't have extensive programming experience so I may be wrong in trying to use an Interface type here, but I believe this is what I should be doing?
Additionally if someone could explain how Spring maps the request parameters to my object fields, that would be much appreciated. Or a link to where this is explained, as I haven't been able to find one!
Thanks
You shouldn't use Interface because Spring needs to instantiate that object, otherwise you will be requiring the property editors OR converters.
Read the following post to know about How Spring MVC Binds Parameter?
Read section "Binding Domain Object" in following link.
https://web.archive.org/web/20160516151809/http://www.jpalace.org/document/92/binding-and-validation-of-handler-parameters-in-spring-mvc-controllers

Allowing Custom XML in Web API Data Contract

I'm developing an ASP.NET Web API service, which allows users to post metadata.
In one of the data contracts that the users post, they're supposed to be able to post their own custom metadata in XML format. This is an example:
<Delivery>
<Type>Direct</Type>
<Time>12:00:01</Time>
<Format>Segmented</Format>
<CustomMetadata>
<ClientReference>R46375683</ClientReference>
<Contact>Me#There.com</Contact>
</CustomMetadata>
</Delivery>
I'm having trouble creating a data contract that successfully deserializes properly, however. For the CustomMetadata node, I have :
[DataMember(EmitDefaultValue=false)]
public XmlNode CustomMetadata { get; set; }
When it gets deserialized, I receive an exception:
"Collection type 'System.Xml.XmlNode' cannot be deserialized since it
does not have a valid Add method with parameter of type
'System.Object'."
I don't fully understand why it's trying to "Add" anything to the XmlNode, but for whatever reason, it's failing. Is there an alternative for doing this kind of thing, such as deserializing to a different type? I tried deserializing to a string, but that gave an exception too.
Data Contract serialisation only supports primitives and a few special types. You must use XmlElement instead of XmlNode.
Try:
[DataMemeber]
public XmlElement CustomMetadata { get; set; }
See http://msdn.microsoft.com/en-us/library/ms733127.aspx
Can you try using XmlElement instead of XmlNode? I believe the serializer only special cases elements on deserialization. XElement should work too.

ASP.NET Web API Deserialize Query Parameters into Nested POCO Action Parameter

Already checked this question but didn't answer.
Background
I have a fully functional RESTful web service written using ASP.NET Web API and it currently supports CORS effectively for cross-origin access from browsers that support CORS. Problem is that current business needs require support of browsers that don't support CORS. I am adding JSON-P support to my web service in addition to supporting CORS and through the magic of action selectors and type formatters, my actual web service code hasn't changed....yet.
Currently I use nested POCO objects (objects that contain other objects) as parameters, for example, for my Post actions. Since I'm supporting XML and JSON incoming, the POST data gets deserialized nicely into the POCO objects, since both XML and JSON support nested deserialization. But to support JSON-P, I have to now emulate a POST through Query Parameters. Getting to the Post action method is successful via an httpMethod Query Parameter and a custom action selector.
Question(s)
First of all, and I ask this after reading responses to other questions, will the registered type formatters even access the Query Parameters for deserializing if I have no request body? The JSON-P request is going to be a simple GET request with no body, so I'm not even sure if it is possible to have a POCO in my action parameter and have it deserialized with a GET request and only Query Parameters.
EDIT: Looks like I may be able to do some MediaTypeFormatter magic with a custom formatter and using the QueryStringMapping. Not sure yet though.
Second, is it possible to deserialize Query Parameters into nested properties of the POCO object? And if so, what is the naming convention for Query Parameters to do this? For example XML of Bob would get deserialized into Message.User.FirstName if the action parameter was of type Message.
EDIT: FormUrlEncodedMediaTypeFormatter has some of the functionality that I want if I could just redirect it to use the Query String instead of the body. But I also don't want a JToken object -- I'd like my POCO, but I think I can deserialize a JToken with JSON.NET. So I'm probably going to steal the code from FormUrlEncodedMediaTypeFormatter and the relate internal class FormUrlEncodedJson to make a custom formatter. Just need to make sure question #1 is possible first.
Example POCOs
public class User
{
public string FirstName { get; set;}
}
public class Message
{
public User User { get; set; }
}
Example "standard" RESTful POST
POST /api/messages
Content-Type: text/xml
<Message><User><FirstName>Bob</FirstName></User></Message>
Example Hypothetical JSON-P Simulated POST
<script type="text/javascript"
src="https://api.mydomain.com/api/messages?callback=MyCallback&httpMethod=Post&User.FirstName=Bob">
</script>
EDIT: Overall Goal: I'm trying to leave the action methods alone right now if possible since they currently handle RESTful CORS-enabled requests. My goal is to add JSON-P support to the calls without changing the method signature. I've got that mostly accomplished; all I have left is being able to deserialize the Query Parameters into the action method parameters when it's a JSON-P request.
Try adding [FromUri] to your action definition, i.e.:
public HttpResponseMessage YourAction([FromUri] YourModel model)
{
...
}
At this point in time it seems that I must create two different paths in the API. Because of the way request parameter deserialization works, and model binding vs. media type formatters, and the lack of a hook in this particular area, I cannot have one single Web API method and have the parameters taken from either the query string or the content based upon various request factors.

Spring MVC Rest: How to implement partial response in Json and XML?

I need to the ignore the serialization (JSon/Jackson and XML/XStream) of some attributes from my object response based on user input/or Spring security roles (like you don't have permission to see the content of this field, but all others are ok etc). How is the best approach to do this in Spring MVC Rest?
Other approach is show only the attributes that are relevant for the api user, like described here http://googlecode.blogspot.com.br/2010/03/making-apis-faster-introducing-partial.html
If you are using Jackson, here are some possible options to modify the Json serialization:
Use the #JsonIgnore annotation - However, this is static filtering, and will not allow you to implement rule-based filtering as you appear to need
Use #JsonFilter - This will allow you to implement an interface in which you can provide your serialization filtering logic. You may find this to be too heavyweight of a solution.
The way I often solve this is to return a Map from my Controller methods instead of the underlying object. You can write processing code that puts the relevant fields from the object into the Map, therefore giving you complete control over what is serialized. You could include a method on the Object to do the conversion. The method could look something like this:
// RequestObj is whatever 'input' object that indicates what should be filtered
public Map<String,Object> convertToMapForRequest(RequestObj request){
// Build return map based on 'this' and request
}

Resources