I'm looking for best way of passing a common parameter between pretty much all of my web API methods. The parameter in this case is a repository identifier as there is a choice on login into the SPA over which database is to be used to read and write data from/to. This choice is then stored in the app and used in all future API calls.
The choices I'm considering are:
Route value - this means adding a route parameter to all of the routes and ensuring it's sent for each call the SPA makes: [Route("api/{repo}/{user}/{id}")]. The advantage here is it's maybe more explicit.
Custom header value which is applied blindly by the app on every API request and used by the API whenever required. It is therefore a requirement that this header is passed. The advantage here is there's a separation of concern - the part of the SPA managing the users screen doesn't need to know which repo it's working with.
Are there any best practise guidelines for parameters that are commonly used in an API? Where's the distinction over when parameters should be passed FromUri and FromBody over using custom header values?
It depends on the situation but if you have made APIs in which every time you need to pass certain parameter then better you send this parameter in header. HTTP header meant to send extra information about request context, but be aware of adding too much header key-value.
Through header and querystring (through URL) you can only send data in key-value pair whereas through HTTP body you can send different types of payload (data) i.e. JSON, XML, txt, FileStream etc.
There are certain limitations on the data size based on which methods choose to send data. Through header you can pass data up to 8KB size for each key-value pair, in querystring you can add up to 2048 chars and through body we can send as much as 0 to >= 2 MB of data (Size may vary from server to server).
For more detail please refer RFC 7231
Its depends of use cases
If you need to share links between users you will definitely need to use path
It is also looks more transparent and understandable
I believe you need to use headers if you want to hide information for the end user
If you are trying to achieve some kind of multi tenancy here I can also propose use different sub domains for each repository and then add midleware/filter/etc to resolve repository based on request subdomain. You can automate subdomain creation (most of popular providers have API to do this)
Related
I am working with .NET 5.0. I have a REST based API currently deployed in production and merchants are already integrated with it. Now there is a requirement that I need to add a few more parameters in request and response as well.
Is that bad practice to add params in existing REST API? Should I introduce a new version, or it is okay to add req/response params in the same version?
EDIT: The additional params are not mandatory
API can be broken in two places: the request (input) and the response (output).
Request
If you introduce new input parameters, and you want to keep backward compatibility in your application, then:
your server side should have reasonable default values for missing input parameters
your server side application should keep the same behavior (return the same output, see below) for the input that has these missing values. In other words, the default values (the "fallback") are good enough to return the same results.
If you don't comply with the above, then your API is broken in terms of input.
Response
The response is tricky, because it depends on your consumers, and on the content type of the response.
If the response's content type is extensible, like JSON or YAML, and your API consumers are aware that new fields can be added to the output in any time, and can be ignored, then your API is backward compatible (namely, not broken) in terms of output.
However, if your consumers expect a strict schema in the response (a fixed amount of existing fields, for instance), then adding new fields (even if they can be ignored) is not acceptable and thus breaks your API.
It depends..
So the answer is: it depends. If new fields are added to the output, then you should either communicate to your consumers about extending the response, or create a new endpoint to your API (/v2/...).
Also, if there are no reasonable fallback values for input parameters, then this, again, requires a v2 entry point of your API.
I want to use an approach which phpbb uses
(with it's PHP Session ID passed as GET parameter of HTTP request,
like http(s)://server/page.php?sid=somestring
).
PHP generates id that is 26 characters long and
ASP.NET generates one that is 24 characters long
ASP .NET changes/rewrites URL instead, what I want to avoid
How it is implemented in ASP .NET ( https://msdn.microsoft.com/en-us/library/aa479314.aspx ):
Web.Config contains something similar to
<sessionState
cookieless="AutoDetect"
sessionIDManagerType="NyNamespace.MyCustomSessionManager, \
CustomAssemblyNameInBinFolder"
>
</sessionState>
Request is processed by MyCustomSessionManager (derived from ISessionIDManager)
with GetSessionID method (which uses Validate method internally)
obtained ID is used within framework (it's not important for now - how exactly)
...
during rendering code uses Response.ApplyAppPathModifier method
which check Session.IsCookieless property, and modifies URL if user disabled cookies.
generated page with modified URLs is sent to browser
http://yourserver/folder/(session ID here)/default.aspx
I don't want to use these scary URLs.
I am aware about 3 problems with cookieless approach:
ability to publish URL with session ID (I will protect from this with fingerprinting and timestamping)
ability to connect from different tabs of browser into same session (it can be solved later)
some people refers to HTTP standarts and says that these standarts prohibit using GET and POST parameters at the same time. (I have different understanding of there RFCs - it is possible to use any parameters in URI in addition to POST parameters, so I will use both types of parameters at the same time)
I want to do following:
Modify MyCustomSessionManager to extract Session ID from GET parameter of reqiest, instead of URL part
generate 26-characters ID based on digital fingerprint (to be able to verify it later) instead of default one
use Response.Filter to replace/patch URLs to id-in-get-parameter in output as in
http://www.drdobbs.com/windows/post-processing-the-output-of-aspnet-pag/212001499
Additionally I want to override ApplyAppPathModifier on HttpResponse (which is sealed,
but there is HttpResponseWrapper class).
But I don't know when to replace response to response wrapper.
Is this viable approach?
There are several similar questions:
Cookieless session from URL to QueryString
Use Session ID from supplied parameter instead of default behavior in ASP.NET MVC3
And some which I can't find again
I am asking mine, because I don't understood exactly,
how to implement writing of session ID into GET parameter of HTTP request.
Let's assume we have a RESTful web service that will calculate UK Royal Mail postage charges.
There would be a number of essential input parameters:
weight of item (grams, int),
length of item (cm, int),
width of item (cm, int),
category of item (letter/parcel, string/enum),
service required (first class/second class/special delivery/etc, string/enum),
destination (domestic/international/maybe further specify the latter, string/enum)
Such an application would be easy to create as a WebAPI. It could be called via a URL such as ...
http://myserver.com/api/mailcharges?weight=150&length=15&width=10&category=letter&service=first&destination=domestic
The web service would then do a simple lookup on its internal tables and return the postage in its response payload.
The beauty of this is that it could then be utilised by a variety of applications within an organisation (or even outside it!). However, this requires that each application that calls the web service needs to be able to populate these parameters; the integers are OK, they are just that - numbers. But the strings or enums are more difficult. The logic for entering and validating these needs to be replicated in every client application. Wouldn't it be nicer if the web service could prompt the user for any which are not passed in or passed as nulls or invalid values. In fact wouldn't it be nicer still if the web service had a user interface which allowed a user to enter any or all of the parameters.
What I am looking for is a cross between a web site and a web service. A web application which can be called via a simple RESTful http request, which pops up a user dialogue, accepts user input, and when the user clicks on a suitable button, does its calculation and returns its answers as a JSON/XML response.
Does anyone have any ideas on how to implement such an architecture? I have tried calling MVC actions/views from within a web api controller but the response is the html for the MVC view, and is returned to the api controller directly rather than being rendered and POSTing back its user input.
I hope I am just being thick, and that the answer is obvious, but all my experiments have so far failed, and any suggestions, no matter how far fetched or outrageous, would be very welcome.
I realize that this is a fairly trivial example, but the same argument goes for much more complicated web services where the replication of user input forms, input validation, complex processing logic etc. across multiple client applications would be far more of an issue than with this example.
if the web service could prompt the user is essentially missing the point of a service. It is no longer a webservice, but a webpage.
In order for internal/external applications/websites to utilize your service, they essentially need to know three things:
where to ask - this is your http://myserver.com/api/mailcharges
what are the arguments - that is weight, length…
what are accepted argument values
While 1. and 2. are usually mere API documentation you seem to have a problem with p. 3 - you want the user to be somehow prompted to choose among possible values and not guess. But you also want the user application not to be responsible for maintaining/validating the list of possible values.
Guess what? You simply need another API. :) An API to describe your arguments.
Let's concentrate on category field. Your API could be extended with a new URL: http://myserver.com/api/getCategories which essentially returns a list of available (currently understood by API) possible category values. This can be JSON, or comma separated string or whatever reliable. Now your end-user GUI-enabled application calls the API, asks for categories, and creates UI accordingly - populating ComboBox or whatever with obtained values. The same is done for other fields. You can. i.e. obtain acceptable ranges of weight or length.
The important thing you mention in your question is validation: logic for entering and validating these needs to be replicated in every client application. This is somehow true, as it essentially depends on the technology used in the end-user application. On the other hand it is very important, that the API performs validation itself! You can never know who is going to use your API. And it is always better to check twice then never.
All,
For a new project that we have started with .NET we wanted to exercise pure REST. Hence we chose .NET Web API which has been released as part of .NET Framework 4.5 (instead of WCF) with the consideration that it enables pure REST nature. But as we explored more based on our requirements, we realized that it doesn't have URI templating support that provides REST like URL formats. we were still OK as we didn't feel much bad about WebAPI having query string kind of formats.
When we engaged a new team, they started to enforce that they need REST kind of URL formats only as it is the standard norm and likes.
When asked about the enforcement they just mentioned that it is a standard and we have to adhere to it which didn't convince me.
So, I am interested to know what does REST architecture provides out of the box? Also having querystring format URI doesn't qualify to be a REST approach?
REST URI: http://myapplicationdomain.com/apps/appId
Querystring URI: http://myapplicationdomain.com/GetAps/appId={appId}
Thanks in advance.
REST is not only the URL format, and REST does not restricts you from using parameters.
One part of REST philosophy is to identify resources, so your resource has URL, and HTTP verbs (Get, Post, Delete, Put, etc.) define operations on this resource.
You can still use parameters, for example
http://myappfomain.com/product/?page=1&pageSize=10
It is a GET request to the list of products (since ID is not specified) and paging/sorting criteria is specified in a query string. It is perfectly correct.
Or
http://myappdomain.com/product/123/?format=json
Here you access product with the ID od #123, but request it to be returned as JSON. It is also fine.
From this perspective it is just more logical that a resource has its own URL. Parameters may add some specifics.
Look at it this way:
URI defines the subject
HTTP Verb defines the operation (what to do)
Query parameters provide some specifics (how to do it)
Hope it helps.
The REST (see wiki Representational state transfer) "style" of the URI is there for a reason. An extract from wiki:
Uniform Interface
...
Identification of resources Individual resources are identified in requests, for example using URIs in web-based REST systems....
Manipulation of resources through these representations When a client holds a representation of a resource, ... it has enough information to modify or delete the resource on the server ...
I used these cites as nice explanation of the fact, that REST style of URI is in fact about resource identification. We can have
1) a table in DB and
2) an ID column which allows to
3) UPDATE or DELETE the record.
The URI in REST does do the same:
1) Identify the resource type (entity/table)
2) Identify the resource ID
3) set the operation
HTTP Method URI Operation
GET \ResourceType\ResourceId SELECT, READ
POST \ResourceType INSERT, Add, create new
PUT \ResourceType\ResourceId UPDATE the record with ResourceID
DELETE \ResourceType\ResourceId DELETE that record
So as we can see, the REST URI style does make sense in the complete context of the resource management
I was thinking ,
The WebApi along with routing mechanism works in such way that it reads the http verb ( GET POST etc...) and then searches for matched method names / parameters :
For example :
If it's GET and the URI is api/Customers/5:
method should start with Get
if it has ID so search a method which accepts int as parameter.
etc. (there are more rules).
I mostly believe they did it using reflection.
Question :
Isn't it a performance hit , for every URI request - to search all this data just to attach a method ?
Where I could easily send a very short string from a client which will imply on the method on the server side ?
Why not doing it the simple way ? Ok cause we want to use http verbs as meaning. OK. but so much operations just to execute a method
example #1
get api/Customers/5
could be
a.ashx?m=gc&id=5 (method=GetCustomer & id=5)
example #2
put api/Customers/5?v=123
could be
a.ashx?m=uc&id=5?v=123' (method=UpdateCustomer & id=5 & value=123)
mine is even shorter.
Dont get me wrong. I believe this api was done by very smart people who knew what they talk about.
Just want o know what am I missing.
Web api has a lot of options that you don't have with HTTP Handler if you don't code it
Full list: http://www.asp.net/whitepapers/mvc4-release-notes#_Toc317096197
OData support (via Queryable attribute)
Content Negotiation
Filters
Model binding and validation
Ability to self host outside of IIS
Link generation to related resources that incorporates routing rules
Full support for routes/routing
Ability to create custom help and test pages using IApiExplorer
Performance comparison HttpHandler vs WebAPI: http://www.west-wind.com/weblog/posts/2012/Sep/04/ASPNET-Frameworks-and-Raw-Throughput-Performance
As always, you need to choose the the technology that suits you best, if you want performance go with Http Handler. If you want flexibility and rest go with Web API. You might want rest if you expose web services that other will consume