Implementing versioning a RESTful API with WCF or ASP.Net Web Api - wcf

Assume i've read a lot about versioning a restful api, and I decided to not version the the service through the uri, but using mediatypes (format and schema in the request accept header):
What would be the best way to implement a wcf service or a web api service to serve requests defining the requested resource in the uri, the format (eg. application/json) and the schema/version (eg player-v2) in the accept header?
WCF allows me to route based on the uri, but not based on headers. So I cannot route properly.
Web Api allows me to define custom mediatypeformatters, routing for the requested format, but not the schema (eg. return type PlayerV1 or PlayerV2).
I would like to implement a service(either with WCF or Web Api) which, for this request (Pseudo code):
api.myservice.com/players/123 Accept format=application/json; schema=player-v1
returns a PlayerV1 entity, in json format
and for this request:
api.myservice.com/players/123 Accept format=application/json; schema=player-v2
returns a PlayerV2 entity, in json format.
Any tips on how to implement this?
EDIT: To clarify why I want to use content negotiation to deal with versions, see here: REST API Design: Put the “Type” in “Content-Type”.

What you are bringing here does not look to me as versioning but it is is more of content negotiation. Accept header expresses wishes of the client on the format of the resource. Server should grant the wishes or return 406. So if we need more of a concept of Contract (although Web API unline RPC does not define one) then using resource is more solid.
The best practices for versioning have yet to be discussed fully but most REST enthusiast believe using the version in the URL is the way to go (e.g. http://server/api/1.0.3/...). This also makes more sense to me since in your approach using content negotiation server has to keep backward compatibility and I can only imagine the code at the server will get more and more complex. With using URL approach, you can make a clean break: old clients can happily use previous while new clients can enjoy the benefits of new API.
UPDATE
OK, now the question has changed to "Implementing content-negotiation in a RESTful AP".
Type 1: Controller-oblivious
Basically, if content negotiation involves only the format of the resource, implementing or using the right media type formatter is enough. For example, if content negotiation involves returning JSON or XML. In these cases, controller is oblivious to content negotiations.
Type 2: Controller-aware
Controller needs to be aware of the request negotiation. In this case, parameters from the request needs to be extracted from the request and passed in as parameter. For example, let's imagine this action on a controller:
public Player Get(string schemaVersion)
{
...
}
In this case, I would use classic MVC style value providers (See Brad Wilson's post on ValueProviders - this is on MVC but Web API's value provider looks similar):
public Player Get([ValueProvider(typeof(RequestHeadersSchemaValueProviderFactory))]string schemaVersion)
{
...
}

Related

How to convert a LinqExpression into OData query URI

There are a lot of answers on how to convert ODataQuery into an Expression or into a Lambda, but what I need is quite the opposite, how to get from a Linq Expression the OData query string.
Basically what I want is to transcend the query to another service. For example, having 2 services, where your first service is not persisting anything and your second service is the one that will return the data from a database. Service1 sends the same odata request to Service2 and it can add more parameters to the original odata request to Service2
What I would like:
public IActionResult GetWeatherForecast([FromServices] IWeatherForcastService weatherForcastService)
{
//IQueryable here
var summaries = weatherForcastService.GetSummariesIQ();
var url = OdataMagicHelper.ConvertToUri(summaries);
var data = RestClient2.Get(url);
return data;
}
OP Clarified the request: generate OData query URLs from within the API itself.
Usually, the queries are so specific or simple, that it's not really necessary to try and generate OData urls from within the service, the whole point of the service configuration is to publish how the client could call anything, so it's a little bit redundant or counter-intuitive to return complex resource query URLs from within the service itself.
We can use Simple.OData.Client to build OData urls:
If the URL that we want to generate is:
{service2}/api/v1/weather_forecast?$select=Description
Then you could use Simple.OData.Client:
string service2Url = "http://localhost:11111/api/v1/";
var client = new ODataClient(service2Url);
var url = await client.For("weather_forecast")
.Select("Description")
.GetCommandTextAsync();
Background, for client-side solutions
If your OData service is a client for another OData Service, then this advice is still relevant
For full linq support you should be using OData Connected Services or Simple.OData.Client. You could roll your own, or use other derivatives of these two but why go to all that effort to re-create another wheel.
One of the main drivers for a OData Standard Compliant API is that the meta data is published in a standard format that clients can inspect and can generate consistent code and or dynamic queries to interact with the service.
How to choose:
Simple.OData.Client provides a lightweight framework for dynamically querying and submitting data to OData APIs. If you already have classes that model the structure of the API then you can use typed linq style query syntax, if you do not have a strongly typed model but you do know the structure of the API, then you can use either the untyped or dynamic expression syntax to query the API.
If you do not need full compile-time validation of your queries or you already have the classes that represent the resources served by the API then this is a simple enough interface to use.
This library is perfect for use inside your API logic if you have need of generating complex URLs in a strongly typed style of code without trying to generate a context to manage the connectivity to the server.
NOTE: Simple.OData.Client is sometimes less practical when developing against a large API that is rapidly evolving or that does not have a strict versioned route policy. If the API changes you will need to diligently refactor your code to match and will have to rely on extensive regression testing.
OData Connected Services follows a pattern where some or all of the API is modelled in the client with strongly typed client side proxy interfaces. These are POCO classes that have the structure necessary to send to and receive data from the server.
The major benefit to this method is that the POCO structures, requests and responses are validated against the schema of the API. This effectively gives you full intellisense support for the API and allows you to explor it's structure, the generated code becomes your documentation. It also gives you compile time checking and runtime safety.
The general development workflow after the API is deployed or updated is:
Download the $metadata document
Select the Operations and Types from the API that you want to model
Generate classes to represent the selected DTO Types as defined in the document, so all the inputs and outputs.
Now you can start using the code.
In VS 2022/19/17 the Connected Services interface provides a simple wizard for establishing the initial connection and for updating (or re-generating) when you need to.
The OData Connected Service or other client side proxy generation pattern suits projects under these criteria:
The API definition is relatively stable
The API definition is in a state of flux
You consume many endpoints
You don't want to manually code the types to serialize or deserialze payloads
Full disclosure, I prefer the connected service approach, but I have my own generation scripts. However if you are trying to generate OData query urls from inside your API, its not really an option, it creates a messy recursive dependency... just don't go there.
Connected services is the low-(manual)-code and lazy approach that is perfect for a stable API, generate once and never do it again. But the Connected Service architecture is perfect for a rapidly changing API because it will manage the minute changes to the classes for you, you just need to update your client side proxy classes more frequently.

How to fix WrongInputException in ASP.NET Core?

I want to use a SOAP web service prepared by another team, used internally in my new REST API prepared in ASP.NET Core. My web service client code was scaffolded with WCF Web Service Reference Provider Tool. I cleaned up code (e.g. I changed property and method names) according to my team's naming convention.
When I send requests by my new REST API, I received WrongInputException. I checked all the parameters from an example request, all of them are in the same place in my C# code consuming scaffolded client.
I don't know what message exactly is sent by my new REST API.
In my case, the main cause of the described behavior and WrongInputException was premature refactoring. I changed the names of properties in the web service client without knowledge of the consequences.
E.g. if the element in the request body is objectRefNum, then I cannot simply change the related property in the scaffolded service reference class, because - without extra configuration - that name is copied with the same letter case to the request body of the SOAP envelope. The SOAP envelope should be encoded in the case-sensitive mode.
To trace the raw request body send by my new REST API in ASP.NET Core, I followed instructions from this excellent answer.
(Note, BTW, that kind of error (applying inappropriate letter case) could be handled by IDE, at least as a warning, but it is not, so: we need to be careful when we make refactoring, even if we have unit tests covering all the paths, and even if we use semantic renaming supported by IDE.)

How is data sent in REST web services

I am learning about web services. I now have good understanding of SOAP. I have few questions regarding REST web services.
1) DO GET, PUT & POST methods in REST web services work exactly the same way as they work with a simple website.
2) GET , PUT & POST methods in REST web services allows us to send/Receive data(say: tweet in Twitter) between client & the web service. Is this message sent(PUT & POST) & Received(GET) in the Body of the POST/PUT method in XML/JSON/other formats or is the file(in a specific format) sent separately.
3) Are there any Browser tools available to see what is Sent & Received in REST web services.
First of all, clarifying a few things. REST is an architectural style, a set of constraints to guide your structural design decisions. REST is not coupled to any particular underlying protocol, so it's not dependent on HTTP, although it's very common.
Second, keep in mind that REST became a buzzword to refer to almost any HTTP API that isn't SOAP, and most of the so called REST APIs aren't REST at all. Most of them are simple RPC over HTTP. I recommend reading this answer for some clarification on that.
Now, to your questions:
1) DO GET, PUT & POST methods in REST web services work exactly the
same way as they work with a simple website.
The problem with your question is that the only exact definition of how those methods work is the one defined by the RFCs, and a simple website might implement it differently. For instance, PUT isn't allowed to be used for partial updates, but many websites and HTTP APIs do that.
As I said above, REST is protocol independent, but respecting the uniform interface constraint and applying the principle of generality, you should stick to the standard semantics of the underlying protocol as much as possible, which means that if you're using HTTP 1.1, you should stick to the behavior determined in the RFCs 7230 to 7235.
2) GET , PUT & POST methods in REST web services allows us to
send/Receive data(say: tweet in Twitter) between client & the web
service. Is this message sent(PUT & POST) & Received(GET) in the Body
of the POST/PUT method in XML/JSON/other formats or is the file(in a
specific format) sent separately.
The format is established in a previous contract between the client and server -- usually in the documentation -- and it's handled during the request using the Accept and Content-Type headers. For instance, if a client wants JSON response, it sends the Accept: application/json header. If the server can't respond with JSON, it should fail with 406 Not Acceptable.
Keep in mind that in an actual REST webservice, you don't use a generic media-type like application/json since that says absolutely nothing about the content other than how to parse it. You should have more specific media-types for your resources, and focus your documentation on those. For instance, an User resource in JSON format can have a custom media-type like application/vnd.mycompany.user.v1+json.
3) Are there any Browser tools available to see what is Sent &
Received in REST web services
In Google Chrome you can use the developer tools, or some client like this or this. You can also use a command line client like curl.
Also, keep in mind that it should be pretty easy to drop-in a generic html+javascript client into a real REST API to make it navigable with a browser. Here is an example of a REST API using HAL+JSON and a generic client.
https://api-sandbox.foxycart.com/hal-browser/browser.html#/
1) Yes, REST functions pretty much exactly the same as a normal HTTP website, for example, GET would retrieve data without changing the state of the server and POST would send data to the web service as a new 'Object', and PUT would modify an existing 'Object'
2) You would enclose the data to be sent inside the body of the request for POST and it would return data back in the body. GET does not accept any data in the body (and you would specify it as part of the path/query parameters ie http://service.com/rest/directory/user1?param=something) but would return the results of the query inside the body. POST would require a message to be posted in one of the forms specified as accepted, most usually JSON. Specifying the Content-Type would indicate to the web server what type of data you are sending and the Accept header would indicate what type you wish your response to be in.
3) In Google Chrome you can use the Developer Tools (Ctrl+Shift+I in Windows) and go on the Network tab to see what is sent and received as a page is loading/performing tasks. You can use DHC or RestEasy to send your own custom requests to REST Services through a GUI, or cURL to do this through a command line
DO GET, PUT & POST methods in REST web services work exactly the same way as they work with a simple website?
yes. they are same anywhere we are using http. read this article specially Request Method section
GET , PUT & POST methods in REST web services allows us to send/Receive data(say: tweet in Twitter) between client & the web service. Is this message sent(PUT & POST) & Received(GET) in the Body of the POST/PUT method in XML/JSON/other formats.
yes they are generally in these formats but can be in any depending on ur requirement.
read this ans for better understanding of content-type and headers in general
Are there any Browser tools available to see what is Sent & Received in REST web services.
as mentioned in one of the comments. Postman is an awesome chrome extension. I generally preffer fiddler over Postman but it is not a in browser tool.

WCF Rest - what are the best practices?

Just started my first WCF rest project and would like some help on what are the best practices for using REST.
I have seen a number of tutorials and there seems to be a number of ways to do things...for example if doing a POST, I have seen some tutorials which are setting HttpStatusCodes (OK/Errors etc), and other tutorials where they are just returning strings which contain result of the operation.
At the end of the day, there are 4 operations and surely there must be a guide that says if you are doing a GET, do it this way, etc and with a POST, do this...
Any help would be appreciated.
JD
UPDDATE
Use ASP.NET Web API.
OK I left the comment REST best practices: dont use WCF REST. Just avoid it like a plague and I feel like I have to explain it.
One of the fundamental flaws of the WCF is that it is concerned only with the Payload. For example Foo and Bar are the payloads here.
[OperationContract]
public Foo Do(Bar bar)
{
...
}
This is one of the tenants of WCF so that no matter what the transport is, we get the payload over to you.
But what it ignore is the context/envelope of the call which in many cases transport specific - so a lot of the context get's lost. In fact, HTTP's power lies in its context not payload and back in the earlier versions of WCF, there was no way to get the client's IP Address in netTcpBinding and WCF team were adamant that they cannot provide it. I cannot find the page now but remember reading the comments and the MS guys just said this is not supported.
Using WCF REST, you lose the flexibility of HTTP in expressing yourself clearly (and they had to budge it later) in terms of:
HTTP Status code
HTTP media types
ETag, ...
The new Web API, Glenn Block is working addresses this issue by encapsulating the payload in the context:
public HttpResponse<Foo> Do(HttpRequest<Bar> bar) // PSEUDOCODE
{
...
}
But to my test this is not perfect and I personally prefer to use frameworks such as Nancy or even plain ASP NET MVC to expose web API.
There are some basic rules when using the different HTTP verbs that come from the HTTP specification
GET: This is a pure read operation. Invocation must not cause state change in the service. The response to a GET may be delivered from cache (local, proxy, etc) depending on caching headers
DELETE: Used to delete a resource
There is sometimes some confusion around PUT and POST - which should be used when? To answer that you have to consider idempotency - whether the operation can be repeated without affecting service state - so for example setting a customer's name to a value can be repeated multiple times without further state change; however, if I am incrementing a customer's bank balance this cannot be safely be repeated without further state change on the service. The first is said to be idempotent the second is not
PUT: Non-delete state changes that are idempotent
POST: Non-delete state changes that are not idempotent
REST embraces HTTP - therefore failures should be communicated using HTTP status codes. 200 for success, 201 for creation and the service should return a URI for the new resource using the HTTP location header, 4xx are failures due to the nature of the client request (so can be fixed by the client changing what they are doing), 5xx are server errors that can only be resolved server side
There's something missing here that needs to be said.
WCF Rest may not be able to provide all functionality of REST protocol, but it is able to facilitate REST protocol for existing WCF services. So if you decide to provide some sort of REST support on top of the current SOAP/Named pipe protocol, it's the way to go if the ROI is low.
Hand rolling full blown REST protocol maybe ideal, but not always economical. In 90% of my projects, REST api is an afterthought. Wcf comes in quite handy in that regard.

Is WCF result as JSON + unparseable curft needed for better security? How is it implemented?

I'm reading about this ajax response that describes ways to prevent Javascript based exploits.
Does it make sense to apply this technique to WCF-based services that return JSON?
How would this be implemented server side?
How would the client consume it?
There's one way WebScriptEnablingBehavior -- the behavior of choice if you want a WCF service that works with ASP .NET AJAX -- deals with this. By default, its response mode is "WrappedResponse". If you watch this in action using Fiddler, it means that every response from the service -- even a simple number -- will wrapped in {d:} wrapper as follows:
{ "d" : return-value }
On the other hand, WebHttpBehavior is XML out-of-the-box, but if you switch it to JSON, you can choose between WrappedResponse and BareResponse. WrappedResponse is similar to WebScriptEnablingBehavior (if I remember correctly), but BareResponse would be unsecure JSON transmitted back as a direct return value.