9

I'm implementing a REST Web API. I'm using the examples from Adam Freeman's Pro ASP.NET MVC5 as a starting point but adapting it into the Web API way of doing it.

The below is my code:

public class AdminController : ApiController
{        
    private IUserRepository _repository;
    public AdminController(IUserRepository repository) 
    {
        _repository = repository; 
    }

    public ActionResult Index()
    {
        return View(_repository.Users);
    }
}

In the book, AdminController implemented Controller not ApiController, but if I do that then I get errors about there being no parameterless constructor. I need the constructor to take parameters so that I can inject the dependencies. So that's why I changed to ApiController but now it won't recognise View.

What do I need to use instead of View for an ApiController?

I did find this question but the answer was basically "you don't need to use an ApiController here, just use Controller" so that didn't help me.

Community
  • 1
  • 1
starsplusplus
  • 1,232
  • 3
  • 19
  • 32
  • 1
    [Difference between ApiController and Controller in ASP.NET MVC](http://stackoverflow.com/q/9494966/2974754) – Yurii Nov 25 '14 at 15:01
  • 1
    You don't return a View from an API controller. But you can return API data from an MVC controller. The solution would be to correct the errors, not try to hack the API controller. Constructor arguments most certainly can be used in controllers for dependency injection. Perhaps you're not wiring up the dependency resolver correctly? – David Nov 25 '14 at 15:02
  • BTW you can inject into `ApiController` and `Controller` -- but you want `Controller` – David Tansey Nov 25 '14 at 15:04
  • http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api – Shekhar Pankaj Nov 25 '14 at 15:04
  • @DavidTansey Is this an X/Y problem? Should I ask a new question about how to fix the parameterless constructor error instead? – starsplusplus Nov 25 '14 at 15:07
  • @Yurly Thanks, I already read that question. It made me think that I should be using an ApiController because I'll be making this project the Web API way, not the MVC way? (hope that's the right terminology, this is all new to me) Was I wrong to interpret it that way? – starsplusplus Nov 25 '14 at 15:09

3 Answers3

17

You are having two different problems. Let's solve them separately.

1. Do I need to use ApiController or Controller?:

Someone already answered this here: Difference between ApiController and Controller in ASP.NET MVC.

The first major difference you will notice is that actions on Web API controllers do not return views, they return data.

ApiControllers are specialized in returning data. For example, they take care of transparently serializing the data into the format requested by the client.

So, if you want to return a View you need to use the simple ol' Controller. The WebApi "way" is like a webservice where you exchange data with another service (returning JSON or XML to that service, not a View). So whenever you want to return a webpage (View) for a user you don't use the Web API.

In other words, the Web API is about returning data to another service (to return a JSON or XML), not to a user.

2. But if I use Controller then I get "parameterless constructor" errors.

Okay, now we've got to your real problem. Don't try to reinvent the wheel and fight with ASP.NET about doing dependency injection! A tool already exists to resolve dependency injection and sort out the "parameterless constructor" error: Ninject.

If you're already using Ninject and still getting that error, you're doing something wrong with Ninject. Try to repeat the installation and configuration steps, and see some tutorials or questions about parameterless error with Ninject use

Community
  • 1
  • 1
Wagner Leonardi
  • 4,226
  • 2
  • 35
  • 41
  • Also, see my query [here](http://stackoverflow.com/questions/27129986/how-do-i-return-the-view-with-an-api-controller#comment42759370_27129986) about the question you linked to in part 1. – starsplusplus Nov 25 '14 at 15:25
  • @starsplusplus, since you're returning a View, it isn't the "WebApi" way. WebApi is used to return a JSON or XML, not Views. You really should use Controller. If you're using Ninject and having the "Parameterless" error, *you are using Ninject wrong*, try to repeat Ninject configuration, and check this answer to get any help: http://stackoverflow.com/questions/12311479/asp-net-mvc-4-ninject-mvc-3-no-parameterless-constructor-defined-for-this-ob – Wagner Leonardi Nov 25 '14 at 15:33
  • *since you're returning a View, it isn't the "WebApi" way. WebApi is used to return a JSON or XML, not Views.* Right, but my question was how to do it in the Web API way? – starsplusplus Nov 25 '14 at 15:37
  • I want to *solve the same problem* in the WebApi way, not *find equivalent syntax*. – starsplusplus Nov 25 '14 at 15:39
  • Do you have to return a View? If so **you don't use WebAPI for this**, WebAPI is about returning data to another service (to return a JSON or XML), not to a user. Do you understand? – Wagner Leonardi Nov 25 '14 at 15:39
  • Thanks for the distinction, that helps. – starsplusplus Nov 25 '14 at 15:40
  • That's nice, I updated my answer solving your new question, all clear now? I had these same questions when learning WebApi too, is a quite confuse, but you'll understant more when you need to work in real life... sending data in JSON or XML to another service, not only sending views to a web user :) – Wagner Leonardi Nov 25 '14 at 15:43
  • *WebAPI is about returning data to another service (to return a JSON or XML), not to a user.* This single sentence made it so much clearer. I think I'll go back to trying to solve the parameterless constructor error. Thanks very much for your help. – starsplusplus Nov 25 '14 at 15:51
  • I'm happy that you get it! Check the last link that I updated in my answer, they had the same trouble (using ninject and having parameterless error) maybe some answer help you, but if not, please close this and open a new specific question about it. – Wagner Leonardi Nov 25 '14 at 15:57
  • 1
    Don't worry, it won't become a chameleon question :) If I have a new question and the other questions' answers don't solve it I'll ask it as a new question. – starsplusplus Nov 25 '14 at 16:01
4

An API controller is a controller which provides a RESTful response. You cannot return a view from it. Instead of doing that, consider returning a response (values) which forces the client that asks for an action to redirect to another controller (passing arguments if necessary) to return a view.

Your case does not look like you need an API; in this case just try this (change what you inherit):

public class AdminController : Controller
{        
    private IUserRepository _repository;
    public AdminController(IUserRepository repository) 
    {
        _repository = repository; 
    }

    public ActionResult Index()
    {
        return View(_repository.Users);
    }
}

I will try to explain what an API should do anyway. A web API should return just information. An HTTP response about what the action should do.

For example, to create a new customer, an API should have a method (decorated with POST) to get information from a client application (could be anything: web, windows, mobile, windows service, etc.). This information should be processed by the API (or other layers in a possible architecture) and return an HTTP status code, for example 200 - OK if it was fine or 400 - Bad Request if an error happened. So, when I said you should consider returning information, you could just return a DTO object to provide a result.

Both types of project use MVC principles, but they are used in a different context. Take a look at these articles:

Also take a look at the ASP.NET website about how they work:

Community
  • 1
  • 1
Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
  • 1
    put some references for him,he need how? not why? – Shekhar Pankaj Nov 25 '14 at 15:03
  • Thanks for getting to the heart of what I'm trying to do. Can you expand on this part in your answer at all? "consider returning a response (values) which makes the client that ask for an action to redirect for another controller (passing arguments if necessary) to return a view." – starsplusplus Nov 25 '14 at 15:42
  • For a POST request, you probably want to return `201 Created` rather than `200 OK`, I think? Apart from that, this is great. Thanks for the explanation. +1. – starsplusplus Nov 26 '14 at 10:04
  • Yes, could be `201 - Created` when resources was created in the server-side. But a POST could return `200 - OK` – Felipe Oriani Nov 26 '14 at 10:05
0

Use Controller to render your normal views. ApiController action only return data that is serialized and sent to the client. But still you want to render view from APIcontroller, then there may be a another way, click on below link for reference :

https://aspguy.wordpress.com/2013/09/10/web-api-and-returning-a-razor-view/

Vaibhav J
  • 1,316
  • 8
  • 15
  • Read the question before answering, he's having problem when use Controller. – Wagner Leonardi Nov 25 '14 at 15:20
  • i think i read the question correctly, he's having problem so he used the APIController, but now he want to know how to return view from APIController. please read the title of this post/question. – Vaibhav J Nov 25 '14 at 15:23
  • @WangerLeonardi Vaibhav has read the question correctly! If one creates an API but for whatever reason wants to support HTML output as well they have to use Razor Engine to render the razor files (aka View). – Aref Karimi Jan 24 '18 at 09:47