Mixing Web Api and ASP.Net MVC Pages in One Project - asp.net-mvc-4

How do I mix Web API and ASP.Net MVC pages in one project?
For instance, I have model User. I would like, within the same project, to have an ApiController that would respond to all the HTTP verbs for managing the User entities, and at the same time have a Controller that would return the appropriate strongly-typed Views depending on the Action requested.
I can't name both controllers UserController. What is the best way around this? Should I name one UserApiController and the other UserController? Any other suggestions?

You can put them in separate namespaces, e.g MyApp.Controllers.UsersController and MyApp.Controllers.WebAPI.UsersController.
This would let you expose similar URI routes in MVC and WebAPI, eg:
/users/1 << MVC view
/api/users/1 << Web API

I haven't changed the namespaces, the only thing that I had to do was register WebApi first, and then MVC route
//First register WebApi router
GlobalConfiguration.Configure(WebApiConfig.Register);
//and register Default MVC Route after
RouteConfig.RegisterRoutes(RouteTable.Routes);
and everything works great!

The WebApi implementation should be added as a separate Area in the MVC application. It is a natural fit. Doing this gives you the separate namespace that Mike Wasson recommended, plus it gives you a natural way to set up the /api routing. You get a separate model folder
Additionally, it is very specifically separated from the rest of the project. If requirements in the future are ever such that you need to separate the api implementation into a separate project, having the api implementation isolated to a separate area makes that breaking it out a lot easier.

Related

Blazor Architecture

I am building a Blazor app and I have a need to reuse a bit of code that returns teh results of a linq query. My question is where do i put general code? What is the accepted place in the structure? I've got the following folders to choose from:
Authentication
Controllers
Data
Models
Pages
Services
Shared
and then once i've got this how do i call this public method? Is it enough that it is public or do i need to create a class variable of type x? Pretty basic stuff but i'm stuck.
I've puyt the methoid in once page component/class anmd then to use it elsewhere I 've created a new new instance of the class component so i can reference the method but is this the best way?
thanks
John
If the page you are reusing has html or css then use a .razor otherwise, use a .cs
Looking at your folder structure, MVC is not a good choice to architect Blazor apps as MVC is for Stateless and Blazor is not Stateless. There are several choices on how to accomplish getting data into a component, my favorite is DI.

MVC based authentication templates in ASP.NET Core 2.0

When creating a new ASP.Net Core web project in ASP.Net Core 2.0, and choosing the 'Individual account' authentication option, the authentication views/controllers where originally implemented using ASP.Net MVC. Recently it appears they have been updated to use Razor pages. My questions is...is there a way I can revert the new project template to using the MVC instead of Razor pages or at the very least is there a way I can see what code the MVC template used to create?
Simply, no. Identity now comes with a Razor Class Library containing a default UI, which as you've noted, is Razor Pages-based. If you want the old-style MVC setup, you'll need to create it yourself. You can scaffold the Default UI pages into your project and then refer to these to move code into controllers/views. Then, when you're done with that, remove the default UI pages in your project, and turn off the default UI in general by using AddIdentity<TUser, TRole> instead of AddDefaultIdentity<TUser> (which adds the default UI under the hood).
FWIW, I used to be totally opposed to Razor Pages until I endeavor the same thing you're about to embark on. After moving all the code into controllers, I started to remember how much of a mess it actually was. There's so much boilerplate code involved in auth: sign in, sign out, registration, password resets, 2FA, third-party login, etc. You end up with monstrous controllers with hundreds or even thousands of lines of code. Even if you try to break it up into many different controllers, that just kind of makes it worse. Long and short, Razor Pages actually works pretty well for something like this. It keeps each unit of functionality self-contained, so you know exactly where your need to go to edit stuff. I'd encourage you to give it a go as-is, first, and see how it works for you.
Also, one of your main concerns may be the Web Forms style of routing with Razor Pages, where you the path becomes the URL, and if you're like me, that probably offends your sensibilities. This can actually be changed, though it's not documented well at all. You can simply specify whatever route you'd like the page to have with the #page directive. For example, you could do something like following in Login.cshtml:
#page "/signin"
Then, you can access the page via /signin, instead of /Identity/Account/Login.cshtml.

Usage of areas in .NET core

I am developing an ASP.NET MVC Core application. In this application I'm using areas. I have multiple areas now: Administrator (for website maintenance), Identity (for identity razor pages) and Public (for visitors).
I like those areas, but I dont' like the fact that I need my visitors url's look like: https://localhost:5001/Public/Home and https://localhost:5001/Public/Catalogue, etc.
I more like urls like https://localhost:5001/Home and https://localhost:5000/Catalogue etc.
Is there any possibility, where I can use areas, except for the visitor part of the website?
I will not recommend to get rid of "area name" in the url, because the routing will not work properly when you have similar page names in different areas! e.g. if you have two areas "public" and "private" and both contains pages with similar name "Index" most probably you will see an error that there is multiple pages using the same route, and thats why areas are exists.
back to your issue, if you are using razor pages you may add the route template directly to the top of razor page:
#page "/catalog"
or if you have parameters:
#page "{id}"
#Url.Page("/catalog")
if you are using MVC, then you may use attribute routing and keep AreaPrefix empty:
[RouteArea("Public", AreaPrefix = "")]
[RoutePrefix("catalog")]
public class CatalogsController : Controller
you can read more about routing in the docs here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2

No AccountController for asp.net core 2.1

I realise in asp.net core 2.1 Identity has been shifted, but can be added to the solution if you add them as a scaffolded item.
It adds all the razor class library for all the pages.
However what I want to do is have the old AccountController way where a client (mobile or web) can post to the account related API's..
What are my options for being able to get the old way back or similar. so that i can use api's from clients
Unfortunately, it doesn't exist any more. I was personally very aggravated by this change, as well as the team's endless pushing of Razor Pages on everyone, which frankly should have been left in the dustbin of history </rant>.
What I have done, personally, is add the scaffold, and then create my own controllers, shuffling and rewriting the Razor Pages code into traditional MVC-style controllers and views. This was not a pleasant experience, though, but I know of no other way if you want it this way.
One thing to note, though, is that the AddDefaultIdentity extension actually adds the default UI, as well, just as if you had scaffolded it into your project. In other words, even if you move everything over to controllers and views and delete all the scaffolded stuff, the Razor Pages routes will still take precedence. Even more unfortunate, there's no good alternative to add AddDefaultIdentity. This is what you'll need instead:
services.AddIdentityCore<ApplicationUser>(o =>
{
// Identity config
})
.AddSignInManager()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<YourContext>();
services.ConfigureApplicationCookie(o =>
{
o.LoginPath = "/signin";
o.LogoutPath = "/signout";
o.AccessDeniedPath = "/signin";
o.ReturnUrlParameter = "returnUrl";
});
Obviously, in the last bit, you'd change the URLs to your own applications routes.

Consume my own REST api with Play Framework

So I am updating a Play 1.2.x application with has the following setup
- controllers
- api
- Documents // create, update, read, delete, list
... // more controllers
- web
- Documents // list, read, etc...
.. // more controllers
The controllers in the api package render data as Json which is used by mobile clients (Android, iPhone).
Now I want to have a plain simple html web app consuming the api. So how can I consume the API from the controllers in the web package?
My goal is to avoid rewriting the api controllers logic in the web controllers logic.
Thanks!
Reusing methods between controllers is not the best practice in my opinion. Shared behavior should be coded in the model and both controllers can then use the same model methods.
Nevertherless if you want to do so, you can extract shared behavior in a public method in your apis controllers wich you can annotate as "#Util" and then call this method from your web controller.
There are not many details in your question, so I do not know if it applies, but usually when I implement REST APIs I let them serve their answers in different formats (JSON and HTML, and if you want JSONP and XML for instance).
The main idea is just to
check the request to know what format is required: either using the accept content type, the url extension, or even a parameter (and some more about it)
pick the right template (or skip a template if you have already correctly built your Json object)
In play there are different ways to do the first part, eg. through your routes: Request Content-Type in Play! Framework for REST webservices ; there is a specific page on Play documentation about this.
But the most important part in this answer is the second point: you should use the same controller and the HTML template should be able to render your page with the very same data that is sent back as json (or maybe a little more)!
NB. if you need to customize things a little more you can access the request object in the controller, check what the requested format is, and act accordingly to return appropriate data using the appropriate template!