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.