asp.net webapi controller, return typed entity or HttpResponseMessage - asp.net-web-api

i would like to know what is the benefit of using HttpResponseMessage as the return type in my ApiController ? compare to returning the typed entity or collection directly.
we were trying to decided on a practice to keep things consistent for the project we are working on.

Returning HttpResponseMessage is useful when you are trying to use your controller layer as the translation between the HTTP protocol and your internal .Net services. It allows direct control over the HTTP payload and headers. It makes it easy to return 202, 204, 304, 303 responses. It makes it easy to set caching headers. You have explicit control over the media type of the response.
By returning an object you effectively adding a "do nothing" layer to your architecture. Consider....
public Foo Get(int id) {
return _fooRepository.GetFoo(id)
}
What is the purpose of this method? What value does it add? At least in MVC land, the controller had the role of matching the model and the view.
When you return objects from an APIController you have to impact the HTTPResponseMessage indirectly using a set of abstractions that are specific to Web API/MVC and have no corresponding concept in the HTTP world. Formatters, ActionFilters, ModelBinders, HttpResponseException are all infrastructure designed to allow the framework to process your HTTP request and response messages behind the scenes.
Returning HttpResponseMessage directly requires that your controller method does the work necessary to return the desired HTTP message.
I don't believe that it adds any complexity to your application, it just makes what is happening visible.
It comes down to whether you want to use Web API as an "object remoting over HTTP" framework (in which case I would also take a look at ServiceStack) or whether you want to take advantage of HTTP as an application protocol.

Related

What are the differences of Flux<T>, Flux<ResponseEntity<T>>, ResponseEntity<Flux<T>> as return type in Spring WebFlux?

I often see three different response return types: Flux<T>, ResponseEntity<Flux<T>>, and Flux<ResponseEntity<T>> in MVC style controllers using Spring WebFlux. The documentation explains the difference between ResponseEntity<Flux<T>> and Flux<ResponseEntity<T>>. Does Spring automatically wrap Flux<T> as either ResponseEntity<Flux<T>> or Flux<ResponseEntity<T>>? if yes, which one?
Moreover, how to decide which one to return, ResponseEntity<Flux<T>> or Flux<ResponseEntity<T>>? What situation or use case would call for using one over the other?
And, from a webclient's point of view, are there any significant differences when consuming the two types of response?
Does Spring automatically wrap Flux as either
ResponseEntity<Flux> or Flux<ResponseEntity>? if yes, which one?
Spring will automatically wrap that Flux as a ResponseEntity<Flux>. For example if you have a web endpoint as follows
#GetMapping("/something")
public Flux handle() {
doSomething()
}
And if you are consuming from a WebClient, you can retrieve your response as either ResponseEntity<Flux<T>> or Flux<T>. There is no default, but I would think it's good practice to retrieve only Flux unless you explicitly need something from the ResponseEntity. The Spring doc has good examples of this.
You actually can consume it as a Flux<ResponseEntity<T>>, but this would only be applicable for more complex use cases.
Moreover, how to decide which one to return, ResponseEntity<Flux>
or Flux<ResponseEntity>? What situation or use case would call for
using one over the other?
It really depends on your use case.
Returning ResponseEntity<Flux<T>> is saying something like,
I am returning a Response of a Collection of type T objects.
Where Flux<ResponseEntity<T>> is saying something more like
I am returning a Collection of Responses, where the responses have an entity of type T.
Again, I think in most use cases returning just Flux<T> makes sense (This is equivalent to returning ResponseEntity<Flux<T>>)
And finally
And, from a webclient's point of view, are there any significant
differences when consuming the two types of response?
I think what you're trying to ask is whether you should be using ResponseEntity<Flux<T>> or Mono<ResponseEntity<T>> when consuming from the WebClient. And the spring doc answers this question quite elegantly
ResponseEntity<Flux> make the response status and headers known
immediately while the body is provided asynchronously at a later
point.
Mono<ResponseEntity> provides all three — response status, headers,
and body, asynchronously at a later point. This allows the response
status and headers to vary depending on the outcome of asynchronous
request handling.

Is there a Best Practice for multiple Http Post - RPC style, custom MediaTypeFormatter or Other

I'm not looking to start a holy war but looking for maybe a document on best
practices for creating APIs which contain multiple HTTP verbs.
I inherited a 4.7.2 Web API project and trying to straighten out some things and
hopefully sometime in the future get to move it to .NET Core.
In the mean time I have a resource that will be gaining new functionality.
To keep this simple, let's just say it is a "document".
Currently there is a [HttpPost] that is used to create the document metadata.
The ask is to extend it to provide "Clone", "Split", "Merge" all of which are
creation types but all have a dependency on an existing document.
I can go the RPC style
api/document/{action}/{id}
api/document/{id}/{action}
which flies in the face of HTTP REST implementations.
The second implementation is a little better but that "action" is not really a "resource".
The other option I have is to have a single HttpPost that looks like the code at the bottom
and pass a custom content-type. If I go this route, I must implement a MediaTypeFormatter
or I get a exception generated. I currently have this implemented and working, it's just
going to be a maintenance nightmare when/if I start adding/changing to use this methodology.
As I said, I'm on 4.7.2 so ConsumesAttribute is not available to me.
The question I have is.... Is there a best practice????
Thoughts?
[HttpPost]
public async Task<IHttpActionResult> Post([FromBody] string metadata)
{
var ct = Request.Headers["Content-Type"]
switch (ct)
{
// Call operation that will handle that Content Type which
// will deserialize document into a specific object type
}
}
Action Content Type
Create application/json
Clone application/vnd.mycompany.create-from-existing.v1+json
Split application/vnd.mycompany.split-from-existing.v1+json
Merge application/vnd.mycompany.merge-existing.v1+json
public class MyContentTypeToStringFormatter : MediaTypeFormatter { }

Api Platform - returning data from external API

I'm currently using API Platform to display some data in Elasticsearch. This works fine, but I now have another feature that I'm looking at.
My application needs to deal with a 3rd-party API that needs to hit an endpoint and return some data.
Within my app, I'd like to be able to hit (/api/logistics/{action} - where action is an endpoint, such as login) and this then hits my app layer and returns data (3rd-party can be re-named)
The API calls to the 3rd party are fine, but I'm unsure how to display the response.
I've seen https://api-platform.com/docs/core/data-providers/ which looks like i can create a custom response.
Do i still need to create an entity/model and configure the #ApiResource() with a controller that uses my Data Provider?
If so, then what do i need to add in my annotation, since I won't have an id identifier
I'm fairly new to API Platform and I've not used the Data Provider functionality before
I will not be storing the data from the 3rd party API, just doing a HTTP call, retrieving the response and hopefully displaying it via Api Platform
Thanks
You are mosly right about the dataprovider. But as the docs page General Design Considerations states, "you have to write a plain old PHP object (POPO) representing the input and output of your endpoint. This is the class that is marked with the #ApiResource annotation. This class doesn't have to be mapped with Doctrine ORM, or any other persistence system."
So no, it does not need to be an Entity, but there must be a class marked with the #ApiResource annotation (but putting it in the Entity folder may help to make the #ApiResource() tag work - or adding the folder of your class in api/config/packages/api_platform.yaml).
For an item "get" endpoint your POPO needs an id. The poperty - or if there is only a getter, the getter - must be marked with the #ApiProperty(identifier=true) tag. Usually the easiest way to make one is by imploding/encoding some strings from the response of the external api call that together are unique for the response and will not change. Your dataprovider will have to explode/decode the id and use the components to make the external api call.
For a "post" operation you need a datapersister instead of a dataprovider. Apip will instatiate and populate your POPO and pass it to the datapersister and from there you can make the call to the external api and return an object as the result. If your object is not the same type of POPO you should specify "output"=TheOutputClass::class or put the operation on the output class and specify "input"=TheInputClass::class (replace TheOutputClass or TheInputClass by the actual class name)
For "put" and "patch" you need both a dataprovider, a datapersister and an id. They can have different input and output classes, see the docs about DTOs.
A collectionoperations with method "get" may seem convenient because you can just pass it any query string but your CollectionDataProvider must return an iterable.

Add ASP.NET MVC Routed URLs to view-model objects (for use in JSON)

I'm writing an application which uses ASP.NET MVC with JSON.NET as the server, sending JSON to the client which is read by Knockout and then displayed with data-bindings. This is all working wonderfully, except for one problem:
I have a class Customer which is used to generate a ReviewAuthorViewModel class - the latter is meant specifically for JSON serialization and removes unnecessary fields, circular references, etc. On the client, I want to render a link to the Customer's profile page, with the URL coming from a defined MVC route "user/{username}". Because I'm sending this via JSON, I don't have a .cshtml page in which I can call Url.Action.
The question is: For an arbitrary object, how do I most efficiently/elegantly get a URL for an action with some data, without a .cshtml view?
I'd prefer a solution that doesn't require extra code in each action, but that may be the only choice apart from recreating the routing tables client-side in JavaScript. Below are the things I've already tried, and what was unsatisfactory with each.
Solution Attempt 1
Call the UrlHelper.Action method in the ReviewAuthorViewModel class. However, the UrlHelper requires a request context. For the sake of separation of concerns, I don't want my view model to have a dependency on System.Web.Routing, nor do I want it to need a request context to function.
Solution Attempt 2
Create a class RouteInformation with members Controller, Action, and Data, and an interface IUrlViewModel with two properties, a get of type RouteInformation and a get/set string named Url. The view models needing links then implement this interface, and controllers look for view models of type IUrlViewModel and run UrlHelper.Action with the information from the view model's RouteInformation instance, storing the result in the Url property.
This one works but without reflection I don't know how to find view models implementing IUrlViewModel within other view models, and it feels very kludgy.
Solution Attempt 1 is the OK solution. In asp.net-mvc, view models are part of presentation layer, designed specifically for use with views. You should not worry about having view model depend on asp.net specific things. In fact, they should be coupled, as they should be designed to maximize simplicity of view generation and data exchange between web server and web client. And it's good solution to create separate view model and not use Customer class directly for clients. It wouldn't have been OK if Customer was dependent on Routing.
In fact, you could set that property in controller -
[HttpGet]
public ActionResult Get()
{
var viewModel = new ReviewAuthorViewModel();
viewModel.ProfilePageUrl = Url.Action("Index", "Profile");
// return viewModel;
}

spring mvc #requestmapping best practice

Checked the official ref, found a million ways to do things.
I guess I have 2 set of use cases.
1. return customized http response, basically I am responsible for filling in status code, response body(either XML or JSON or text).
2. return Model and View. view is a jsp page typically and fill in the view with data from modle.
My question is which is a better way to go? it possible to mix them together. In my first use set, is it possible to return a View? also is it possible to have both on them in one method. something like if A return customized http response, if B return ModelAndView.
Thanks!
The return value from any request handling method (i.e. on marked with the #RequestMapping annotation must either identify a view (that will generate the HTTP Response) or generate the HTTP Response itself.
Each handler method stands alone; by that I mean, you can return a view name from some handler methods and generate the HTTP Response in other handler methods.
Check out 15.3.2.3 Supported handler method arguments and return types in the Spring 3x reference document at http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/
As an option to generating the HTTP Response in the handler method, you could setup multiple view resolvers; one or more for normal view resolution (jsp pages, tiles, etc.) and one or more for "special" view resolution (XML, JSON, etc.). For the "special" views, you may want to create your own view class that extends org.springframework.web.servlet.view.AbstractView.
You can accomplish something similar to what you are describing using the ContentNegotiatingViewResolver, which can deal with serving different content based on a request, with no changes required to your #RequestMapping annotations, or in fact anything in you're controllers.
There are plenty of resources on how to use this method, including this and this

Resources