I have a ASP.NET web API project and since it does not support having 2 body parameters, I use a JObject parameter and then extract the actual parameters from it. Like this.
Public bool mymethod(JObject data){
myclassA a = data["a"].toObject<myclassA>();
myclassA b = data["b"].toObject<myclassB>();
}
But the 2 class types implement ISerializable and I need the JSON.NET to ignore it. I have set up the default JSON.NET serializer to do that and it works fine when serialization is done automatically.
But I need to get a reference to the built in JSON.NET serializer so that I could use it like this in the above code.
myclassA b = data["b"].toObject<myclassB>(defaultSerializer);
Currently I create a new instance of the JSON.NET serializer and use it. But how can I get a reference to the default built in serializer in the asp.net WEB API ?
Also I cannot change anything in class types as this is sort of a legacy app that I'm converting to web api. Thanks.
Try this:
JsonSerializer serializer = JsonSerializer.Create(Configuration.Formatters.JsonFormatter.SerializerSettings);
That should give you the same serializer Web API uses.
Related
I am currently working on a Spring Boot project and I am fairly new to template engines. This will also be my first own private project with Spring Boot.
I would like to know whether it is necessary to include a template engine, such as Thymeleaf, while developing a web application with Spring Boot. I'm using PostegreSQL for the database.
I read under another post that a template engine is not needed, if the backend framework uses JSON for data exchange, because template engines are for rendering retrieved data to HTML for the client. I retrieve JSON objects from the database, can I leave template engines out of my project then?
If any more details are needed, leave a comment below.
No they aren't necessary, in fact most new projects that require web-pages are using single page applications now like Angular, React, Vue, ... over thymeleaf or jsp.
Aside from that a Spring project doesn't always need web pages, for instance when you are just creating a REST API for other applications to call on, or when you are automating things like: a mail service / printing / ... You name it.
However, when you DO want a simple solution with some pages that aren't all that dynamic or complex, pivotal / VMware does recommend to use thymeleaf (over jsp and other solutions) because it integrates easily.
I read under another post that a template engine is not needed, if the backend framework uses JSON for data exchange, because template engines are for rendering retrieved data to HTML for the client. I retrieve JSON objects from the database, can I leave template engines out of my project then?
This is partly true. Yes, Thymeleaf and alike are mostly intended to render data to HTML. They can render any text data, including JSON, but there are tools better suited for the job. On other hand it does not matter how you store the data in your database or what database you are using. You can't just skip rendering (serializing) the response so it does not matter how you store it. What matters is what you want to return as response. For HTML Thymeleaf or even JSP are suitable, but for JSON you may want to use Jackson or Gson instead.
You didn't mentioned the technology you are going to use, so for my examples I'll assume you intend to use Spring Web MVC. Lets take a look at "traditional" controller:
#Controller
public class GreetingController {
#GetMapping("/greeting")
public ModelAndView greeting(#RequestParam(value = "name", defaultValue = "World") String name) {
return new ModelAndView("greeting", "greeting", new Greeting(name));
}
}
When you make GET request to "/greeting", Spring will call greeting and get the object it returns. In this case it contains the model (the data we want to render) and the view (the template file to use). Then it will try to find a view (something like greeting.html or greeting.jsp) and use template engine like Thymeleaf (or whatever else is configured) to render it (typically to HTML).
What if we want to return JSON instead? In this case we need to:
modify greeting to return Greeting instance instead of ModelAndView
Use RestController instead of Controller. This will tell Spring MVC that we want to directly serialize the object returned to JSON (or similar format) instead of using template to do that.
Here is the modified example:
#RestController
public class GreetingController {
#GetMapping("/greeting")
public Greeting greeting(#RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(name);
}
}
Spring MVC still needs some help to serialize the Greeting instance to JSON. But if you use Spring Boot and the web starter, you don't have to worry about it. It will include Jackson for you.
This is in no way exhaustive answer. As a matter of fact it skips a lot of details, but I hope nevertheless it is useful one. If you want to create REST API using JSON, this Building a RESTful Web Service guide is a good place to start. If you follow the Starting with Spring Initializr steps you'll get a project setup with only what is needed (well maybe with a bit extra but I would not worry too much about it).
Since REST based controller methods only return objects ( not views ) to the client based on the request, how can I show view to my user ? Or maybe better question what is a good way to combine spring-mvc web app with REST, so my user always get the answer, not in just ( for example ) JSON format, but also with the view ?
So far as I understood, REST based controller would be perfectly fitting to the mobile app ( for example twitter ), where views are handled inside the app and the only thing server has to worry about is to pass the right object to the right request. But what about the web app ?
I might be wrong in several things ( correct me if I am ), since I am trying to understand REST and I am still learning.
To simplify things - you basically have two options:
1) Build Spring MVC application.
2) Build REST backend application.
In case of first option - within your application you will have both backend and frontend (MVC part).
In case of second option you build only backend application and expose it through REST API. In most cases, you will need to build another application - REST client for your application. This is more flexible application because it gives you opportunity to access your backend application from various clients - for example, you can have Android, IOS applications, you can have web application implemented using Angular etc...
Please note, that thins are not so simple, you can within one application have both REST backend and REST client etc... This is just very very simplified in order that you get some general picture. Hope this clarified a little things.
There is some additional clarification related to REST and views worth learning. From your question, I can see that you mean "view" in a sense of UI(user interface) and typical MVC usage. But "view" can mean different things in a different contexts.
So:
JSON can be considered as a view for data
JSON is a representation of the resource, just like HTML is
JSON doesn't have style (unless you are not using a browser
extension, which most the users are not using)
The browser is recognizing HTML as a markup language and applying a
style to it
Both are media types
Both JSON and HTML are data formats
Both can be transferred over the wire
This method returns a view
#RequestMapping("/home")
String home(Model model) {
return "home"; // resources\templates\home.html
}
This method Returns String
#RequestMapping(value = "/home")
#ResponseBody
public String home() {
return "Success";
}
If you annotate a method with #ResponseBody, Spring will use a json mapper to generate the response. Instead of annotating every method with #ResponseBody you can annotate your class with #RestController.
If you want to return a view, you need to annotate the class with #Controller instead of #RestController and configure a viewresolver. Bij default spring will use thymeleaf as a viewresolver if you have spring-web as a dependency on the classpath. The return type of the method is a String that references the template to be rendered. The templates are stored in src/main/resources/templates.
You can find a guide on the spring website: https://spring.io/guides/gs/serving-web-content/
I want to get io.swagger.models.Swagger object in my system, which is a restful backend based on jersey and swagger.
I saw in class ApiListingResource there is such a statement
Swagger swagger = (Swagger) context.getAttribute("swagger");
, which can retrieve the swagger object from servlet context.
Can I do the same in my own code? This seems not a contract that the attribute name will always be "swagger". So I dare not.
Is there any reliable way to retrieve the object?
You can rely on the context (yes, it is set to the name swagger, or with your own logic by extending BeanConfig
I am currently developing an OData service using Web Api 2 and EF6 with a Code First Approach. My controllers inherit from the normal ApiController Base.
I have decorated my action methods with the Queryable attribute and have also enabled Query Support in the WebApiConfig file. Through my CORS policy, I have specified the DataServiceVersion and MaxDataServiceVersion as part of my Accept and Exposed Headers.
Strangely, my odata endpoint seems to not return the DataServiceVersion as part of the response header but, if my controllers inherit from the ODataController base I am able to see it in the response.
Is there a way to enable this header while using ApiController as the base.
This header is needed as datajs requires it on the client side.
First to answer your question:
Yes, you can expose the DataServiceVersion http header yourself. It's custom code though, not a setting on an existing component.
Add a "Filter" to your global http configuration. A filter is a class derived from "System.Web.Http.Filters.ActionFilterAttribute".
for example;
internal class DataServiceVersionHeaderFilterWebAPI : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
actionExecutedContext.Response.Content.Headers.Add("DataServiceVersion", "3.0");
actionExecutedContext.Response.Content.Headers.Add("Access-Control-Expose-Headers", "DataServiceVersion");
}
}
Then configure this filter to be used (in application start of global.asax)
GlobalConfiguration.Configuration.Filters.Add( new DataServiceVersionHeaderFilterWebAPI() );
This will allow your cross domain OData query from a security perspective. There is however another issue with this;
OData is a specification larger than just the request URI's & HTTP headers. It also specifies how to exchange model information and the actual data exchange is a predefined object structure. Simple, but still a predefined structure.
object.d = service returned content
You will have to implement all those pieces of the specification ($filter,$metadata,$top, return formats, etc) yourself.
Some food for thought.
As per the title, I'm seeing that my read-only model properties are not serialized in my Web API project. MVC 4 Web API, VS2010.
I've seen a multitude of posts like this stackoverflow question that state that the MVC 4 Web API beta did not support JSON serializing of read-only properties. But many additional references stated that the final release used JSON.NET instead of DataContractJsonSerializer so the issue should be resolved.
Has this issue been resolved or not? If not, am I forced to put in fake setters just to get serialization?
Correction, it does seem to work with JSON (sorry!), but XML exhibits the problem. So same question as before but in the context of XML serialization.
The default JSON serializer is now Json.NET. So readonly property serialization should work without you having to do anything at all.
For XML, in 4.5 we added this flag to the DataContractSerializer:
http://msdn.microsoft.com/en-us/library/vstudio/system.runtime.serialization.datacontractserializersettings.serializereadonlytypes.aspx
You should be able to write something like this:
config.Formatters.XmlFormatter.SetSerializer(myType, new DataContractSerializer(myType, new DataContractSerializerSettings() { SerializeReadOnlyTypes = true });
Place this code in a function called by GlobalConfiguration.Configure in the Application_Start. By default this would be WebApiConfig.Register().