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.