Restful way to perform a data changing action - c#

I'm trying to stay Resftful, and follow protocols. I have an "Organisation" domain object, and have the usual POST/GET/PUT/DELETE operations:
POST https://www.example.com/api/organisation saves a new org.
GET https://www.example.com/api/organisation/{id} gets an org by it's ID
etc
Something a user can do from the client side (Website, mobile, etc) is set their default organisation. On the database side, we're just setting a default flag against the org they want to be defaulted.
But the API side, I'm not sure how to do, and keep it within good practice. At the moment, I have a method in my code:
[HttpPost]
public async Task<IActionResult> SetDefaultOrganisation()
I am not sure how to expose that to the API.
https://www.example.com/api/organisation/setdefault/{id}
That doesn't seem right. I don't want to do a PATCH, as.. the api must describe whats happening. It's not an any-item-can-change.
Is https://www.example.com/api/organisation/{id}/setdefault a more acceptable option?

One important point in restful endpoints is to be resource centric and not process centric.
That's mean if you have a verb (an action, like save or add) in you endpoint, you have a problem in your design.
In your question you wrote
Something a user can do from the client side (Website, mobile, etc) is set their default organisation
So from a resource point of view, the main resource here is the user.
With this point the endpoint can be like this (a POST or PUT)
/api/user/{userId}/orgranizations/default
And the body:
{ orgID : 1234}

Restful way to perform a data changing action
In REST, the way we pass information to the web server is by editing the website.
This is normally done in one of two ways
We GET a representation of the resource, make edits to our copy, and then deliver the revised representation to the server
We fill in form, and deliver the representation of the form data to the server.
From the perspective of REST, these two patterns are the same ones that you use for editing any resource (that's the uniform interface constraint at work: our general purpose tools don't need to know anything about the meaning of the edits we are making).
Therefore, the design problem is to identify which resource (document) includes the representation of the information you want, and what representation (schema) you will use to communicate that change of information.
From the perspective of general purpose REST components, we don't care what the document is -- that's the server's problem; we only care about the string literal used to identify the document.
General purpose components also don't care about spelling conventions; /a472a51b-7e36-404b-a985-1fc79d1b7464 is a perfectly satisfactory identifier. What this degree of freedom means is that you can choose identifiers that are easy for human beings to understand, and identifiers that are easy for your implementation to route.
/api/organisation/{id}/setdefault
From the point of view of a general purpose components, this is fine. Human beings, however, a likely to object -- because this looks like it identifies an action, and what we really want is an identifier that tells us what the document is.
So that might be /api/organization/{id}, if somewhere in the document that describes the organization we have a list of users for whom this is the default organization.
But I think it would be more common to have something like /api/profiles/{userId}, where the profile document includes information about what the default organization is for each user.
If you needed a fine grain resource, then it might instead be something like /api/profiles/{userId}/defaultOrganization or even /api/defaultOrganizations/{userId}
(The ordering of path segments is something you decide upon based on how you want to take advantage of the relative references, as defined by RFC 3986).

Related

Rest API Return Either Properties based on role or different entity

I'm curious when building a proper restful resource, what is the best action to take returning a resource based on a user's role.
For example,
If User 1 calls, GET: api/Users/1
That user should get the base user object (first name, last name, email) along with proprietary information like SSN.
But if User 2 calls, GET: api/Users/1
That user should get the base user object along with maybe their mutual friends they share.
Is this something that is advocated in a restful resource, or would be easier to separate these concerns into something more specific, like api/Users/1/sensitive, and api/Users/1/Friends?
If the former is acceptable, would this be something manageable through inheritance?
Thanks!
Hopefully you've made progress since you asked this question.
I will rephrase the statement made in this SO answer:
It is perfectly under the ambit of REST to return different representations of the same resource based on constraints such as:
Accept header: (e.g. different format like application/json or application/xml)
Authorization: i.e. based on what the caller is "authorized" to see.
The only mandate from REST is that the URI for a resource must be the same. So, consider:
/api/User/1 as the URI for the User resource with ID of 1: Perfectly fine per REST
Whereas:
/api/User/1/private
/api/User/1/public
Isn't RESTful as it provides two URIs for the same resource.

Web API 2 Routing - should ID's always be included even if they are not necessary?

So this is more of a design question, but i think it is one worth questioning.
Here is my dilemma. I am ending up with some quite complex routing while designing an API for consumption. here is an example:
Route("/people/{personID}/phonenumber/{phoneNumberID}/operation/{operationID}/data")
Now this route gets data performed in an operation for a specific phone number for a specific person.
Due to the fact that i can get the operation data solely by the operationID, I really do not need to include personID, or phonenumberID. However this data is tied directly to all of the ID's that are previous to it. Thus, creates "chain of command" if you will.
For instance i could still drop the operationID to get all operations performed on a specific phone number. Like so:
Route("/people/{personID}/phonenumber/{phoneNumberID}/operation")
In this case, the PhoneNumberID is now relevant and needed in order to get the operations neccessary. In the previous example PhoneNumberID did not do anything due to the fact that i had the explict operationID to retrieve data for.
On to my question already!
SO! Should i always include all id's in the route even if they are not needed to actually retrieve the data? Or is this a case of poor design and I should really just rethink how I am doing this? Something just feels off in my gut.
You should try to follow RESTful design. If it's not needed for the resource someone is trying to consume then leave it out. Try to make the API as clear and simple as possible.
If you need to create complex or more detailed API methods you can always have those served via a HTTP POST request for large responses.
Keep things simple. Keep the API clean. Clear well defined Controllers that only take what is necessary for that specific resource.

Making a Saas MVC App...need customer specific views, resource files, and logic

I am building a hosted business SaaS application using MVC 4/C# 4. I'd need to have customer specific resource files, css, views, and business logic that leverage a base code layer as much as possible. How would each of these (resource files, css, views, logic) need to be structured to accomplish this?
I realize this is probably a very in depth answer...but I have no idea where to start or what to search for to begin to research this. Any pointers so I can research further?
Here are my initial thoughts on each:
Views
Use a Switch statement based on user to return different views.
CSS
Use switch statement in view to specify which css to load
Resource Files
I'm not using them now but need to implement, so not sure exactly how they work. From what I've seen you can specify a resource file at the class MetaData level, which is a compile time thing. Not sure how you would change this at the user level. I can see here, how to change it based on culture...but not by a user profile attribute (like the company they belong to).
This looks like a start...will review more.
Business Logic
In my services layer, I could implement switch statements...but that seems messy. Is there a way to create a new classes that override the base classes but only for certain users? Or putting these in a separate project/dll and only using that dll reference for a certain user?
I used to work on the IBM iSeries, and they had the concept of a library path that could be set by user at login. You'd have a custom code path that overrode the base code path libraries. Is there anything similar in MVC?
Data Localization
In my database, I have a table for Orders and another for OrderStatuses, which may be displayed in a drop down for the user to select a status. These statuses may be 'Open' and 'Closed'. But another customer may want that in Spanish...How would you handle this?
Any other considerations I am missing?
Use switch statement
Any time someone is writing object-oriented code and mentions a switch statement to control variable requirements, alarm lights begin to flash.
When you have similar but different requirements, polymorphism is your friend.
Without knowing full details of your requirements it is difficult to provide a specific answer, but consider using the factory pattern / dependency injection to provide objects appropriate to a specific user (or more probably, to the company associated with a specific user).
UI Layer
Generally speaking you could use a factory to return controller instances, based on a common subclass, that implement requirements for a specific user/customer and return views appropriate to that user.
I'm not well enough versed in the specifics of wiring routes in ASP.Net MVC to suggest how specifically to set that up, but it feels like the right approach. Perhaps another poster can shed more light.
Business Logic
This is a classic use of polymorphism, when requirements vary significantly. Alternatives to per-customer classes include configuration-driven behavior and rules engines. The best choice depends on your specific sitation.
Data Localization
Things like order status in the DB should not be bound to a text like 'Open'. They should be bound to a binary representation (e.g. an INT). Leave it to the View to translate that meaning into something specific to the user's language.
In a SaaS application we have developed we have clients who have their own private domains so being able to support something like that was a must. We had to be able to support:
www.mycompany.com/u/clientname
clientname.mycompany.com
www.clientname.com
On of the things we considered was how we could use a single deployment/code base to handle all of these clients. What we ended up with was a Base system that could be extended through the use of "plugins" which are basically class libraries named "APP.Clients.{ClientName}".
We wrote a custom ViewEngine that allows us to make use of these plugins to load Views, Controllers and even Controller Actions from the clients custom plugin to over-ride the base site.
What we ended up with is similar to what people call "portable areas" or basically external views and controllers in an Assembly.
Clients can share a common "network" database or they can be rolled off in to their own database. Most all of the config comes from reading the current URL and having logic that can determine which "client" it is and loading their settings and processing their customization.
Being able to load the client views required adding in additional search locations for Master Pages, Views and Partial Views (why we have a custom ViewEngine).
There is no simple answer and what works for one SaaS project may not work exactly the same for another. Your architecture will likely be similar but your business needs will dictate where your project takes you!

Questioning the use of DTOs with restful service and extracting behavior from update

In the realm of DDD I like the idea of avoiding getters and setters to fully encapsulate a component, so the only interaction that is allowed is the interaction which has been built through behavior. Combining this with Event Sourcing I can get a nice history of what has been actioned and when to a component.
One thing I have been thinking about is when I want to create, for example, a restful gateway to the underlying service. For the purposes of example, lets say I have a Task object with the following methods,
ChangeDueDate(DateTime date)
ChangeDescription(string description)
AddTags(params string[] tags)
Complete()
Now obviously I will have instance variables inside this object for controlling state and events which will be fired when the relevant methods are invoked.
Going back to the REST Service, the way I see it there are 3 options:
Make RPC style urls e.g. http://127.0.0.1/api/tasks/{taskid}/changeduedate
Allow for many commands to be sent to a single endpoint e.g.:
URL: http://127.0.0.1/api/tasks/{taskid}/commands
This will accept a list of commands so I could send the following in the same request:
ChangeDueDate command
ChangeDescription command
Make a truly RESTful verb available and I create domain logic to extract changes from a DTO and in turn translate into the relevant events required e.g.:
URL: http://127.0.0.1/api/tasks/{taskid}
I would use the PUT verb to send a DTO representation of a task
Once received I may give the DTO to the actual Task Domain Object through a method maybe called, UpdateStateFromDto
This would then analyse the dto and compare the matching properties to its fields to find differences and could have the relevant event which needs to be fired when it finds a difference with a particular property is found.
Looking at this now, I feel that the second option looks to be the best but I am wondering what other peoples thoughts on this are, if there is a known true restful way of dealing with this kind of problem. I know with the second option that it would be a really nice experience from a TDD point of view and also from a performance point of view as I could combine changes in behavior into a single request whilst still tracking change.
The first option would definitely be explicit but would result in more than 1 request if many behaviors needed to be invoked.
The third option does not sound bad to be but I realise it would require some thougth to come with a clean implementation that could account for different property types, nesting etc...
Thanks for your help in this, really bending my head through analysis paralysis. Would just like some advice on what others think would be the best way from the options or whether I am missing a trick.
I would say option 1. If you want your service to be RESTful then option 2 is not an option, you'd be tunneling requests.
POST /api/tasks/{taskid}/changeduedate is easy to implement, but you can also do PUT /api/tasks/{taskid}/duedate.
You can create controller resources if you want to group several procedures into one, e.g. POST /api/tasks/{taskid}/doThisAndThat, I would do that based on client usage patterns.
Do you really need to provide the ability to call any number of "behaviors" in one request? (does order matter?)
If you want to go with option 3 I would use PATCH /api/tasks/{taskid}, that way the client doesn't need to include all members in the request, only the ones that need to change.
Let's define a term: operation = command or query from a domain perspective, for example ChangeTaskDueDate(int taskId, DateTime date) is an operation.
By REST you can map operations to resource and method pairs. So calling an operation means applying a method on a resource. The resources are identified by URIs and are described by nouns, like task or date, etc... The methods are defined in the HTTP standard and are verbs, like get, post, put, etc... The URI structure does not really mean anything to a REST client, since the client is concerned with machine readable stuff, but for developers it makes easier to implement the router, the link generation, and you can use it to verify whether you bound URIs to resources and not to operations like RPC does.
So by our current example ChangeTaskDueDate(int taskId, DateTime date) the verb will be change and the nouns are task, due-date. So you can use the following solutions:
PUT /api{/tasks,id}/due-date "2014-12-20 00:00:00" or you can use
PATCH /api{/tasks,id} {"dueDate": "2014-12-20 00:00:00"}.
the difference that patch is for partial updates and it is not necessary idempotent.
Now this was a very easy example, because it is plain CRUD. By non CRUD operations you have to find the proper verb and probably define a new resource. This is why you can map resources to entities only by CRUD operations.
Going back to the REST Service, the way I see it there are 3 options:
Make RPC style urls e.g. http://example.com/api/tasks/{taskid}/changeduedate
Allow for many commands to be sent to a single endpoint e.g.:
URL: http://example.com/api/tasks/{taskid}/commands
This will accept a list of commands so I could send the following in the same request:
ChangeDueDate command
ChangeDescription command
Make a truly restful verb available and I create domain logic to extract changes from a dto and in turn translate into the relevant
events required e.g.:
URL: http://example.com/api/tasks/{taskid}
I would use the PUT verb to send a DTO representation of a task
Once received I may give the DTO to the actual Task Domain Object through a method maybe called, UpdateStateFromDto
This would then analyse the dto and compare the matching properties to its fields to find differences and could have the
relevant event which needs to be fired when it finds a difference with
a particular property is found.
The URI structure does not mean anything. We can talk about semantics, but REST is very different from RPC. It has some very specific constraints, which you have to read before doing anything.
This has the same problem as your first answer. You have to map operations to HTTP methods and URIs. They cannot travel in the message body.
This is a good beginning, but you don't want to apply REST operations on your entities directly. You need an interface to decouple the domain logic from the REST service. That interface can consist of commands and queries. So REST requests can be transformed into those commands and queries which can be handled by the domain logic.

How do I represent different product levels and feature access in ASP.NET MVC3?

Before I embark on a journey down the paths of learning ASP.NET MVC3, I wanted to try and get soem recommendations on something I know I'll run into. If I have an application with different user/product levels that result in different users being able to perform different functions (e.g. user has signed up for the base level of the product, so they cannot upload audio while users on higher "tiers" can) are there recommendations on how I could handle this cleanly.
Example 1: Have the model or controller do X and have different Y or Z for each product level.
Example 2: Have inline markup in the view that displays feature available to "upper level" roles based on the result of a helper method.
I was thinking maybe there is a way to have different views and/or models and determine which one to hook up to a request based on some criteria.
Thanks, any suggestions would be appreciated.
That should definitely go into both places. For example, if your free tier does not allow for custom domains, whereas your paid ones do, simply removing an input for domain name will not suffice: a user might be able to hand-craft a POST request and include missing account.customDomain value. Hence, you'll have to check for tier features in the controller as well.
As for where and how to specify these tier restrictions, I too have this problem facin me at the moment. What I came up with is a simple XML file where I specify tier capabilities:
<tiers>
<defaults allow-custom-domain="false" allow-branding="false">
<tier name="free" upload-limit="10MB" />
<tier name="platinum" allow-custom-domain="true" allow-branding="true" upload-limit="2GB" />
</tiers>
And then a simpe C# class for encapsulating access to this spec and you're all set.

Categories