Can struts2-json-plugin accept upper camel case parameters? - struts2

I'm using struts2(struts2-json-plugin) to handle Content-Type=application/json request,
everything is fine where params style is lower camel case,like {"region":"China","version":"v4"}.
But it can't work when params is upper camel case,like {"Region":"China","Version":"v4"}.
I've already read struts docs(https://struts.apache.org/plugins/json/),and still not find the way to solve.
this is part of my struts.xml:

It can't work with case insensitive json objects because names are translated into Java class variables of the action class that are case sensitive.
The json plugin contains the interceptor named json which you should configure to the action to deserialize json content from the request. This answer points to some classes responsible for serialization/deserialization and populating Java objects.
If you don't want to populate the action then you should not use this interceptor. Instead manually parse the request with this or any other third party library to get the JSONObject. Or you could rewrite the interceptor and comment that code that is using JSONPopulator but deserialize the object with JSONUtil.
If you want to transform json objects with lower case names to camel case then you should override one of these classes before the population process to correspond to Java class variables names.

Related

Web API - How to accept comma separated list of parameter values via query string

I have a Web API project I am working on in Visual Studio 2013, and I'd like for my Controllers to accept a comma separated list of values via the query string, similar to this:
http://localhost:12345/api/Procedures/1?embed=doctors,drugs&fields=fieldA,fieldB,fieldC
The reason for this is that I'd like to be able to control if related resources (additional tables) are queried via custom embedding using the embed parameter, and control what fields are returned from the base object using the fields parameter.
I've done some searching on Google but most of what is being suggested relates to extending IModelBinder (http://www.strathweb.com/2013/04/asp-net-web-api-parameter-binding-part-1-understanding-binding-from-uri/) or setting up a custom ActionFilterAttribute (Convert custom action filter for Web API use?) which seems like overkill for something relatively simple.
FYI I am using an Entity Framework dbContext class to connect to my database.
The comma character does not have any specific meaning in HTTP query strings so it does not get treated as a separator by out-of-the-box model binding mechanisms.
As far as I know the approach you mentioned with custom attributes is the simplest you can get. And it does not look like an overkill considering you will only implement the attribute once and use everywhere.

How do I side load a serialization of the current scope?

I'd like to append a serialization of the current scope with my json response. While the current scope is available to the ActiveModel:: Serializer, it's not necessarily associated with the model being serialized; so I'm unsure how to include it.
My first instinct is to just create a wrapper which merges the model serialization and scope serialization. I think this wrapper would break some conventions though.
Is there a pattern for side-loading this context?

in a webservice is the endpoint aware of domain classes or it just passes request parameters to the service class?

I am writing some webservices using spring. I wanna know what's the argument to the service methods: domain objects or request parameters? for example a "User" object or a bunch of strings containing name, e-mail, etc.
Depending on your configuration (and the method signature) you will receive unmarshalled objects (Jaxb for instance), the MessageContext and so on.
Take a look in the documentation, you'll find some examples and everything you need to know about the service methods and parameters.

Backbonejs updating Model with idAttribute set to Id

I'm trying to update a backbone model, the server side is asp.net mvc 4. I'm getting:
"System.ArgumentException: An item with the same key has already been added" exception.
The reason is because backbone is sending Id and id to the server as properties, and the JsonValueProvider tries to add this to a dictionary.
Here is my model:
var Task = Backbone.Model.extend({
url: "/tasks/task",
idAttribute: "Id"
});
This is send to the server via Put request:
{"Id":294912,"Task":"test","DueDate":"2012-03-24T02:00:00.000Z", "id":294912}
Is there a way to prevent backbone in sending the "id" property?
The problem here is because the conventions in C# is not the same as in JavaScript. In C# classes have properties that starts with capital letters (Pascal Case) and it's the norm in JavaScript to start your properties in lower case (Camel Case).
Thus when serializing view models the default behavior of the JSON.NET serializer is to serialize the object exactly with the same capitalization of properties. I could rename the properties on the view model to be camel case, but it would be as "weird" as to have properties with pascal case in your JavaScript objects.
So instead to force Backbone into a non convention way, I've change the serialization of the objects to convert the Pascal case properties into Camel case properties by leveraging JSON.NET's Contract Resolver functionality.
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
JsonSerializer serializer = JsonSerializer.Create(settings);
JsonConvert.SerializeObject(object, Formatting.None, settings);
Now this creates consistency on the client side with my code and with all the cool libraries out there.
Sounds to me like the issue is in your server-side code, not with the call from Backbone. A PUT is an edit operation on the server, so you're updating an existing entity. You need the ID property to identify the model on the server and update the properties that have changed.
If ASP.NET MVC is complaining that the model already exists in the database, you are trying to do an INSERT instead of an UPDATE. We'd need to see the controller and data access code to see where things are going awry.
UPDATE: What happens if you leave off the idAttribute property? From the Backbone documentation:
A special property of models, the id is an arbitrary string (integer id or UUID).
If you set the id in the attributes hash, it will be copied onto the model as a
direct property.
The id attribute should be sent by default; it looks like you're forcing it to be included a second time.
Under idAttribute in the docs:
A model's unique identifier is stored under the id attribute. If you're directly communicating
with a backend (CouchDB, MongoDB) that uses a different unique key, you may set a Model's
idAttribute to transparently map from that key to id.
ASP.NET MVC's model binding should be able to cope with id vs. Id.
UPDATE: Found a good blog post that describes using a view model to aid in serializing your C# objects into the format Backbone expects. This seems like a reasonable, if slightly annoying, solution.

Accepting multiple representations for POST

I'm getting up to speed with the WCF Web API. I want to expose an endpoint that can accept notes, via the POST method. My issue is, I want to support multiple representations for notes. For example, I might want to accept a note using a custom XML serialization that we're using elsewhere, or as an atom:entry element. I already have formatters that can deserialize these into a Note class (our own custom class) or as a SyndicationItem.
The question comes though, how do I define the method? I've currently got this:
[WebInvoke(UriTemplate = GetNotesUriRoot,Method="POST")]
public HttpResponseMessage PostNote(ObjectContent item,HttpRequestMessage request)
Which fails when starting up:
The service operation 'PostNote' will never receive a value for the input parameter 'item' of type 'ObjectContent'. Ensure that a request HttpOperationHandler has an output parameter with a type assignable to 'ObjectContent'.
I initially tried having two separate methods (with appropriately typed parameters), but they can't share the same endpoint name. The current effort (using ObjectContent) was based on other posts I could find that suggested that it could be a parameter. There is no common base type or interface between Note and SyndicationItem
We're using v0.6.0 of the WCF Web API
You need to have a parameter / return type of type Note and your formatters will (de-)serialize it to / from the required representation.
[WebInvoke(UriTemplate = GetNotesUriRoot,Method="POST")]
public HttpResponseMessage PostNote(Note note)
then in your request the content-type header will determine how the object is deserialised. You don't need to worry about deciding how to deserialise, the decision is made for you, as long as the relevant formatter exists (I've not delved in to formatters yet as json/xml have been enough for me so far)

Resources