I understand if I use springMVC and pass a json object to the controller, it will try to bind the json object to the controller pararmenter, but how to handle the binding error? I use something like this but seems not userful.
public String save(#RequestBody #Valid SomeList list, BindingResult result){
if(result.hasError()){
System.out.println(result);
}
}
Generally, you can return the same view that submitted the data. If you have <form:error> tags there, they will be displayed (because of the binding information).
But this is most certainly an ajax call, so what you can do is set a specific response status in the if body:
response.setStatus(HttpServletResponse.NOT_ACCEPTABLE);
and then look for that status code (406) in the ajax response handler. If you want precise validation information, you can try serializing the binding result itself as a response.
System.out.println will do next to nothing. Basically what it's saying is output the binding result to the server jvm std out.
Since you're returning a String, I'm going to assume you're returning a view name, so you might want to redirect the user to an error page.
Related
I'm building an Api Controller and I need to serialize my List to JSON as my action result.but It seems that such statements doesn't work
return Json(data, JsonRequestBehavior.AllowGet);
How can I achieve this ?
As you mentioned that you are using WEB API, I'm assuming it has the JsonFormatter configured. With that said, the responsibility to convert you action result into a JSON is not of your action but from the Media Type Formatter chosen as part of the Content Negotiation process.
That said, it's enough for your Action to return the actual List type and the Web API Media Type formatter will take care of formatting it to JSON.
For example, let's say that data is a List<Foo> where Foo is some type that you created. It is enough for your controller action to be:
public List<Foo> GetFoo()
{
var data = GetListOfFoo();
return data;
}
Have you tried using a JSON serializtion class?
I have had success using the ideas put forward in this article:
Serializing a list to JSON
Or, if you don't want to use serialization, the example for an action result using JSON in MSDN just uses a generic list object.
I have the following REST endpoint:
#POST
#Path("/id/{id}/doSomething")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
public Response doSomething(#PathParam("id") final String id, MyObject foo) {
// does some stuff; checks for a null foo and handles it
}
The MyObject class has a single String field called justification.
I'd like to be able to hit this endpoint with no content at all, or with JSON that maps to the MyObject class. I'd like either way to work. In other words, foo can be instantiated, or foo can be null; I have code to handle both cases.
The problem is that the JSON content appears to be required to this endpoint, not optional. So during testing, I'm having to send JSON to the endpoint, or I receive a 500 error. Even if that JSON is just {} (I can also send { justification: "blah blah" } and that works as well). But sending no content at all results in a failed call; never even hits the endpoint.
So, my question is, how can I set this endpoint up so that I can POST to it with no content at all, or with JSON in the body that maps to foo, and have either way work?
Ultimately, I just need a way for the user to be able to send a justification to this endpoint, but not have to. And because justifications can be long, I can't have it as a query param or a path param.
Thanks!
You are not going to be able to hit the endpoint with no content at all because your endpoint says #Consumes({MediaType.APPLCIATION_JSON}). Besides there has to be some content while you're trying to POST to a class while using a web service.
Like you said, even if it is a NULL or a {}, it doesn't matter as long as it has some content coming in.
Passing no content to the service works only when you're making a GET request.
For all other HTTP methods such as POST,PUT and DELETE, you will mandatorily HAVE to send some data.
As a solution to your problem, what you possibly could do is that - check if the content you have received is a NULL or a {} and do no processing at all for them.
If you still have a confusion in the answer, depending upon whether you're using SOAP or REST, this thread should help you.
How to express 'null' value from web service as real null or empty string instead of 'null' string
Hope this helps.
I was able to accomplish what I wanted by writing a second method annotated with the same REST path. This second method does not have an #Consumes statement, and does not have the second parameter in its method declaration. Looks like this:
#POST
#Path("id/{id}/doSomething")
#Produces({ MediaType.APPLICATION_JSON })
public Response doSomethingWithoutJustification(#PathParam("id") final String id) {
doSomething(id, null);
}
This new method maps to the same path, but does not expect JSON and doesn't expose a second parameter. So when I POST with nothing in the request body at all, it hits doSomethingWithoutJustification, and when I do provide JSON in the request body, it hits doSomething. Of course, if I provide anything other than valid JSON in the request body, I receive a 500 response from the service, as I'd expect.
I'd hoped to specify an optional parameter with a single method, but this solution works perfectly.
I am using an upload control to send a file to a JsonResult, but I am also sending up a JSON string as a second parameter. This is all getting posted with the Content-Type:multipart/form-data;
[HttpPost]
public JsonResult UploadDocument(HttpPostedFileBase file, DocumentViewModel model)
{ ... }
I know MVC is capable of binding directly to a viewmodel if the content type is set to application/json but I don't think it's possible for me to set that in this case.
Is there any way for me to get MVC to automatically bind my posted json string to model?
That's not possible out-of-the-box. You will have to manually deserialize the JSON string parameter that you would read from the request to your view model inside the controller action or write a custom model binder for it that will do the job. Ideally you shouldn't be posting the model data as a JSON string but rather respect the content type you specified : multipart/form-data. So the correct way to handle this scenario is to modify the client code that is sending the request in order to respect the content type.
As I was unable to change the content-type I found this blog to be exactly what i needed.
"... our whole request stream(data) won’t be json string. Only the guest parameter will be supplied as json string..."
http://ishwor.cyberbudsonline.com/2012/07/fun-with-aspnet-mvc-3-custom-json-model-binder.html
I'm using the WebApi httpclient to build up a .net api library for use against a REST webservice.
The rest service returns JSON.
Problem i am having is that for one request, it is possible that i get diffrent JSON formats back.
If the query was successful, I get back a JSON array which I have made a strong c# type to hold it.
Using the ReadAsAsync< T > method to get it out of the content.
If the request had a bad api key in or another error happens, the rest service returns a JSON object with some properties like status=error and an explanation message etc.
I cant then just use the ReadAsAsync< T > method as I dont know what format is comming back. I don't know much about the JSON linq library but is there a way I can put the JSON response into some JSON holder object and then check if there is a status=error in it and then use the correct deserialization to my strong type.
I seem to be able to store it in a JRaw object but don't know where to go from here.
Many thanks.
If the request had a bad api key in or another error happens, the rest service returns a JSON object with some properties like status=error and an explanation message etc.
In this case, the status code returned will not be successful. You can do a check on the status code and then deserialize your response content appropriately:
if (httpResponseMessage.IsSuccessStatusCode)
{
// Deserialize your JSON array
}
else
{
// Deserialize the error
}
You can use error handling in this case
try
{
//Deserialize your JSON Array..this will throw an exception in case of type mismatch
}
catch(Exception e)
{
//Deserialize your JSON object which will give you Error code or message
}
a Json WCF service method looks like this:
getFoo(MyDataType data){ ...
WCF automaticly translates the HTTP request that looks like:
randomGuy{
name:'John',
age:18
}
into the C# defined type
MyDataType{
string name {get;set;}
int age {get;set;}
}
But if I encrypt the request content, instead of receiving a request that looks like
randomGuy{
name:'John',
age:18
}
I will receive
wceweuicn23cb38v934vb398v03c264vb834gv3v7b3vb3647v34vb3v83vh38v43vhv3hv
Is there any way to first decrypt the request content into randomGuy{
name:'John',
age:18
} before WCF translates the JSON object into the .net defined type MyDataType?
To me, you have about 2 options:
Option 1: Use SSL for the connection so the message is protected.
Option 2: Intercept the message
In summary, I believe that the answer you are looking for are along the lines of an IClientMessageInspector which will allow you to manipulate messages and intercept them if neccessary on you WCF client. This article should explain it somewhat - enter link description here
Looks like the IDispatchMessageInspector or IDispatchMessageFormatter may help you in this case. And in general check the System.ServiceModel.Dispatcher namespace - there are other helpful staff.
The idea with IDispatchMessageInspector, that you are able to change (decrypt in your case) the incoming message before it's converted to a .NET object from JSON one.