11

If I build a Web API Project in Asp.Net Core 1.x, and I want to build the front-end in the same Project or Solution, is it possible to create front-end pages and use Razor with Visual Studio's Intellisense?

The application is built around an API for public consumption, but since my application will use the same data, I thought it would make sense to consume my own API instead of building separate methods or constructs for API calls vs "regular" MVC (call the controller, gets the model data, return the view). A client will have their own front-end and get the data. I will have my own front-end, but I want it integrated in the same VS Solution.

One downside is I lose my Intellisense because I am building it around consuming the JSON returning from the API. I understand that an API is about returning data, not Views. I'm trying to get the best of all worlds and be more productive with Visual Studio features.

All I have read is older. SO has older question as well. I read a a lot about returning a View with an API, but I'm not sure I want that. I want to do like a normal non-Web API project and API project at the same time.

Is this possible?

My understanding is no/sort of because the whole point of Razor is that it is done on the server and the API is for clients outside your application. In other words, I'd need to build a controller that called my API controllers, so I get Intellisense which seems a bit redundant and harder work on the server.

Some possibilities:

Building REST APIs using ASP.NET Core with Razor syntax

ASP.NEt MVC using Web API to return a Razor view

asp.net mvc consuming asp.net web api end point

EDIT: This seems to be logical, https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/areas

EDIT: Here is what I did, using this as a guide:

https://msdn.microsoft.com/en-us/magazine/mt763233.aspx

I created an Area in my Project. Under this I created the name of an Area and under this I created Controllers, Views (and under this Home).

In my Startup.cs file I added,

    app.UseMvc(routes =>
    {
        routes.MapRoute(name: "areaRoute",
          template: "{area:exists}/{controller=Home}/{action=Index}");

        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}");
    });

The URL is localhost:port/AreaName

From within my Controller, I was able to reuse the services from my Service Layer, an abstraction I had decided on earlier in the project.

namespace books.Areas.Controllers
{
    [Area("Books")]
    public class HomeController : Controller
    {
        private readonly AppSettings _appSettings;

        public HomeController(Microsoft.Extensions.Options.IOptions<AppSettings> appSettings)
        {
            _appSettings = appSettings.Value;
        }
        // GET: /<controller>/
        public IActionResult Index()
        {
            var myConn = _appSettings.ConnectionString;
            var getBooks = new BookLoanService(myConn);
            return View(getBooks.GetAll());
        }
    }
}

This is the same Service Layer my API controller uses. The Service Layer has (I am using Dapper),

public List<books> GetAll()
        {
            using (IDbConnection db = new SqlConnection(_connectionString))
            {
                string SqlString = "SELECT TOP 5 last_name, first_name FROM books";
                var myBooks = (List<books>)db.Query<books>(SqlString);
                return myBooks ;
            }
        }

Once I was able to get my types, I was able to use Razor in my Index in my Area:

@model System.Collections.Generic.List<books>
@{

}
<html>
<body>
    @foreach(var person in Model)
    {
        <ul><li>@person.last_name</li></ul>

    }
</body>
</html>

Without modification, I am still able to use my api/values type of URL to get to my API, and I will be able to refresh part of my page after that initial server rendering by calling the API via Ajax.

Community
  • 1
  • 1
johnny
  • 19,272
  • 52
  • 157
  • 259
  • I kind of did this in reverse. I created an MVC project and then just set up some of my endpoints to be use like api endpoints (hitting them with postman etc). I haven't complete it but so far so good? – nurdyguy Jan 25 '17 at 21:08
  • A quick alternative viewpoint. What you've done is clever but I would argue that it's mixing presentation and data access (although I have heard of applications that return such snippets working just fine). I wouldn't be afraid of breaking things up in to different projects for specific concerns. In my experience, WEB API is a thin veil over the meat of an application. All your hard work seems to be being done by your services so I'd argue having an MVC or equivalent project that also consumes them also may not be a great deal of work and would give you a bit more freedom. – Christopher Thomas Jan 27 '17 at 02:27
  • The main reason I did it was for intellisense. I didn't know another way to have both API and non-api and intellisense and two separate projects. It's not intellisense per second. It's more above the typing with razor and productivity with type checking. – johnny Jan 27 '17 at 02:55
  • Couldn't you just use attribute routing to achieve the same result and have the Api action and the mvc view action within the same controller? Have a private method that processes the logic, and both actions call this private method? – Muqeet Khan Feb 08 '17 at 05:43
  • @MuqeetKhan I do not know. I have to try it. – johnny Feb 08 '17 at 14:36

0 Answers0