API Design – Should You Write Your Back-End as an API?

api-designasp.net-mvcmvc

I had a heated discussion today about our MVC application. We have a website written in MVC (ASP.NET), and it usually follows the pattern of do something in the view -> hit the controller -> controller builds a model (calls a Manager that gets the data, builds the model in the controller method itself) -> model goes to view -> rinse & repeat.

He said that our code was too tightly coupled. For example, if we wanted a desktop application as well, we would not be able to use our existing code.

The solution and best practice he said is to build an API, and then build your website on top of your API, and then building a desktop application, mobile app, etc. is very simple.

This seems like a bad idea to me for various reasons.

Anyway I can't seem to find anything by googling that might discuss this practice. Does anyone have any information about pros, cons, why you should, why you shouldn't or further reading?

Some reasons I think it's a bad idea:

  • It's way too abstract to run your backend off an API. You're trying to make it too flexible which will make it an unmanagable mess.

  • All the stuff built into MVC seems useless, like roles and authentication. For example, [Authorize] attributes and security; you will have to roll your own.

  • All your API calls will require security information attached, and you will have to develop a token system and whatnot.

  • You will have to write complete API calls for every single function your program will ever do. Pretty much every method you want to implement will need to be ran off an API. A Get/Update/Delete for every user, plus a variant for each other operation eg update user name, add user to a group, etc. etc. and each one would be a distinct API call.

  • You lose all kinds of tools like interfaces and abstract classes when it comes to APIs. Stuff like WCF has very tenuous support for interfaces.

  • You have a method that creates a user, or performs some task. If you want to create 50 users, you can just call it 50 times. When you decide to do this method as an API your local webserver can named-pipes connect to it and no problem – your desktop client can hit it too, but suddenly your bulk user creation will involve hammering the API over the Internet 50 times which isn't good. So you have to create a bulk method, but really you're just creating it for desktop clients. This way, you end up having to a) modify your API based on what's integrating with it, and you can't just directly integrate with it, b) do a lot more work to create an extra function.

  • YAGNI. Unless you're specifically planning to write two identically functioning applications, one web and one Windows application for example, it is a huge amount of extra development work.

  • Debugging is much harder when you can't step through end-to-end.

  • Lots of independent operations that will require lots of back and forth, for example some code might get the current user, check the user is in the administrator role, get the company the user belongs to, get a list of other members, send them all an email. That would require a lot of API calls, or writing a bespoke method the specific task you want, where that bespoke method's only benefit would be speed yet the downside would be it would be inflexible.

  • Probably some more reasons these are just off the top of my head.

It just seems to me like unless you really need two identical applications, then it's really not worth it. I've never seen an ASP.NET application built like this either, you'd have to write two separate applications (the API and your code) and version control them both as well (if your user page gets a new field, you'd have to update the API and your consuming code simultaneously to ensure no ill-effects or put lots of extra work into keeping it robust).


Edit: Some great responses, really starting to get a good idea of what this all means now. So to expand on my question, how would you structure an MVC app to follow this API structure?

For example, you have a website that displays info about a user. Under MVC, you have:

View – (CS)HTML page that displays a UserViewModel
Controller – Calls GetUser() and creates a UserViewModel that it passes to the view
Manager class (sort of your API) that has a GetUser method.

The controller does GetUser() but you want a desktop app too. This means your GetUser needs to be exposed via some kind of API. You might want a TCP connection, either WCF, or perhaps Remoting. You also want a mobile app which will be RESTful since persistent connections are flaky.

So would you then write an API for each one, a WCF web service that has a method GetUser() and the code just does return new UserManager().GetUser() ? And an mvc 4 web api method that does the same thing? While continuing to call GetUser directly in your MVC controller method?

Or would you choose the solution that would work for all three (web api REST service) and build everything on that, so all three apps make API calls (the mvc ones, to the local machine).

And is this just a theoretical perfect scenario? I can see large overheads in developing this way, especially if you have to develop in a way that will let you do operations in a RESTful manner. I think some of this has been covered in the replies.


Edit 2: After reading more stuff, I've put a comment below that I think might explain it. The question is a bit of a trick question I think. Should you write your back-end as an API had me confused thinking there should be a single webservice that everything (mvc app, desktop app, mobile app) calls to do stuff.

The conclusion I have come to is that what you should really do is make sure your business logic layer is correctly decoupled. Looking at my code, I do this already – the controller will call GetUser() on a manager, then create a view model from it to render with a View. So really, the business logic layer is an API. If you want to call it from a desktop app though, you'll need to write something like a WCF service to facilitate calling it. Even just having a WCF method called GetUser() that contains the code return MyBusinessLayer.GetUser() would be sufficient. So the API is the business logic, and WCF / web api etc. are just titbits of code to let external applications in to call it.

So there is some overhead, in that you have to wrap your business logic layer in different APIs depending on what you need, and you will have to write an API method for each operation you want your other apps to do, plus you will need to sort out a way to do authentication, but for the most part it's the same. Stick your business logic in a separate project (class library), and you will probably have no issue!

Hopefully this interpretation is correct. Thanks for all the discussion/comments it has generated.

Best Answer

Yes you should.

It not only makes your back end re-usable but allows for more security and better design. If you write your backend as part of a single system, you're making a monolithic design that's never easy to extend, replace or enhance.

One area where this is popular at the moment is in Microservices. Where the backend is split into many little (or even large) services that each provide an API that the client system consumes. If you imagine using many 3rd party sources of data in your application you realise you might be doing this already.

One other benefit is that the construction and maintenance of each service can be handed off to a different team, they can add features to it that do not affect any other team producing product. Only when they are done and release their service do you them start to add features to your product to consume them. This can make development much smoother (though potentially slower overall, you would tend to get better quality and understandable)


Edit: OK I see your problem. You think of the API as a remote library. It's not. Think of the service as more of a data providing service. You call the service to get data and then perform operations on that data locally. To determine if a user is logged on you would call "GetUser" and then look at the 'logged on' value, for example. (YMMV with that example, of course).

Your example for bulk user creation is just making excuses - there is no difference here, whatever you could have done in a monolithic system can still be done in a service architecture (e.g. you would have passed an array of users to bulk-create, or a single one to create. You can still do exactly the same with services).

MVC is already based around the concept of isolated services, only the MVC frameworks bundle them into a single project. That doesn't mean you lose anything except the bundled helpers that your framework is giving you. Use a different framework and you'll have to use different helpers. Or, in this case, rolling your own (or adding them directly using a library).

Debugging is easy too - you can thoroughly test the API in isolation so you don't need to debug into it (and you can debug end-to-end, Visual Studio can attach to several processes simultaneously).

Things like extra work implementing security is a good thing. Currently, if you bundle all the code into your website, if a hacker gains access to it, they also gain access to everything, DB included. If you split it into an API the hacker can do very little with your code unless they also hack the API layer too - which will be incredibly difficult for them (ever wondered how attackers gain vast lists of all website's users or cc details? It's because they hacked the OS or the web server and it had a direct connection to the DB where they could run "select * from users" with ease).

I'll say that I have seen many web sites (and client-server applications) written like this. When I worked in the financial services industry, nobody would ever write a website all-in-one, partly as it's too much of a security risk, and partly because much development is pretty GUIs over stable (i.e. legacy) back-end data processing systems. It's easy to expose the DP system as a website using a service style architecture.

2nd Edit: Some links on the subject (for the OP):

Note that when talking about these in context of a website, the web server should be considered the presentation layer, because it is the client that calls the other tiers, and also because it constructs the UI views that are sent to the browser for rendering. It's a big subject, and there are many ways to design your application - data-centric or domain-centric (I typically consider domain centric to be 'purer', but YMMV), but it all comes down to sticking a logic tier in between your client and your DB. It's a little like MVC if you consider the middle, API, tier to be equivalent to your Model, only the model is not a simple wrapper for the DB, it's richer and can do much more (e.g. aggregate data from 2 data sources, post-process the data to fit the API, cache the data, etc.):