Calling controllers in different folders in ASP.NET WebAPI - c#

I have an 100% javascript application inside my ASP.NET WebAPI project. This application consumes all the data from my API methods.
Now, I have been requested to create a simple portal built in Razor and HTML also inside my WebAPI project (so like a MVC project).
So I have created a folder under "Controllers" folder named "Portal" where Im placing all my portal exclusive controllers.
Here is the Controllers structure folders:
This is my Razor web application views structure:
So when I run the application I can see the Login page view (under "Account" folder). When I click my Login button, I call my CommonController (Portal) to render a Left menu but I get the error:
I guess because I have 2 CommonControllers, but 1 is for serving my javascript application and the other is for my Portal application.
The line in my Index.cshtml that calls the Common controllers is:
<div class="page-header page-header-blue">
#Html.Action("Header", "Common")
<h1><i class="icon-bar-chart"></i> Dashboard</h1>
</div>
In my WebApiConfig.cs I have the following Web Api Route:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}"
);
So I don't know how to tell it that I want to call CommonController that is under "Portal" folder.
Any clue or advice on how to do this and the best practice?
UPDATE:
I have create other route for my Portal controllers:
config.Routes.MapHttpRoute(
name: "DefaultMvc",
routeTemplate: "portal/{controller}/{action}"
);
Seems to work but in my index.cshtml calls : #Html.Action("Header", "Common") how can I tell the action to call Portal Common and not just Common ?

I think you can use areas for your case.
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Billing_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
And you need update Application_Start method
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Area in MVC 5 with example - step by step

Related

Why does GlobalConfiguration.Configure not apply the authorization attribute to the MVC controllers?

I have a asp.net mvc project (.NET 4.6.1) which also has a web api in the same project.
The api folder has got the web api controllers.
The Controllers folder next to the api has got all mvc controllers.
In the App Start folder's FilterConfig.cs there is nothing. In the RouteConfig.cs there is class with RegisterRoutes method which has the route handler:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Matter", action = "Index", id = UrlParameter.Optional });
In Startup.Auth.cs there is cookie based auth code.
In WebApiConfig.cs there is following code:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new MyAPIAuthAttribute());
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
MyAPIAuthAttribute is defined in another file. It inherits from System.Web.Http.AuthorizeAttribute and overrides HandleUnauthorizedRequest to return a custom message along with 401 status code.
In the global.asax there is following code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
So it looks like RouteConfig.RegisterRoutes(RouteTable.Routes); registers the routes for the mvc project. GlobalConfiguration.Configure(WebApiConfig.Register); registers the filter and routes for the webapi project.
Issue:
For example - when I enter the webapi controller's GET action method in the browser then it return Unauthorized 401. Where as when I enter the mvc controller's GET action method then it doesn't perform authorization.
My question is - Why isn't the authorization configuration defined in the global.asax (above methods) applied to both mvc and web api controller actions? Since it is globally configured, I was expecting it to be applicable to all controllers in the project.
I think the solution is to either use [Authorize] or a custom class that inherits from AuthorizeAttribute and place it into the FilterConfig.cs for it to apply to the mvc controlelrs?

Redirect routing in ASP.NET Core 2.1

I have a main project with some controllers, e.g. HomeController containing an action "Index". This action is reached by www.mysite.com/home/index.
Then I have another project called "plugin", which is referenced within the main project.
There is a controller, e.g. CustomerController. An action within this controller contains a routing attribute "[Route("edit")]".
This action is reached by www.mysite.com/customer/edit. But I want that this action can be reached by www.mysite.com/plugin/customer/edit containing the name of the project (or another name).
How can I do this without setting routing attribute for every controller in my "plugin" project?
Btw.. I'm using NopCommerce 4.1 if it's necessary to know..
This is scenario for Areas.
1) Inside your plugin create folder structure
Areas
..Plugin
....Controllers
....Views
2) Inside controllers create base plugin controller "PluginController" where you set Area attribute
[Area("Plugin")]
public class PluginController : Controller
{
...
}
3) Make all your plugin controllers inherit from PluginController
public class CustomerController : PluginController
{
...
}
4) Add support for areas into route builder
app.UseMvc(routes =>
{
routes.MapRoute(
name: "defaultWithArea",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Now all actions inside your plugin will require www.mysite.com/plugin/ ...
I'll also note that If you wish to retrieve action urls from outside the plugin you need to specify area of the controller like so:
#Url.Action("Edit", "Customer", new { Area = "Plugin" })

Admin App with the landing page, routing

So far when I open root location, it is an admin home page (i.e. www.example.com), and i would like to make an landing page in that root location, but all admin things i would like to have in separate folder (i.e. www.example.com/admin/).
In example routing option for 'uses' currently is www.example.com/uses/ and I would like to have it in www.exaple.com/admin/users, but I dont want to change the project structure only routing. How can i make it with the minimal change?
EDIT:
I have tried registering routes in MvcApplication class in Global.asax.cs, but it didn't work
public static void RegisterRoutes(RouteCollection routes){
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
But this didn't work out.
For Asp, I would reference the following exert from Microsoft:
Routes
A route is a URL pattern that is mapped to a handler. The handler can be a physical file, such as an .aspx file in a Web Forms application. A handler can also be a class that processes the request, such as a controller in an MVC application. To define a route, you create an instance of the Route class by specifying the URL pattern, the handler, and optionally a name for the route.
You add the route to the application by adding the Route object to the static Routes property of the RouteTable class. The Routes property is a RouteCollection object that stores all the routes for the application.
You typically do not have to write code to add routes in an MVC application. Visual Studio project templates for MVC include preconfigured URL routes. These are defined in the MvcApplication class, which is defined in the Global.asax file.
Src. https://msdn.microsoft.com/en-us/library/cc668201.aspx?f=255&MSPPError=-2147217396
What I would do is create an ADMIN controller, and then set up routes something like so: {controller}/{page}/{action}
Alternatively, you can follow this solution to rewrite routes to subfolder: https://stackoverflow.com/a/17074898/2267583

Integrating MVC3 to webforms - MVC Routing not working

I have followed all steps on this link including web.config changes and adding required assemblies.
ASP.Net and Webforms in Harmony
I have installed MVC3 into the webforms project and Implemented a controller and registered its routes in Application_Start method of Global.asax.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Here is the controller
public class HomeController : Controller
{
//
// GET: /Default1/
public ActionResult Index(int? id)
{
ViewData["Message"] = "Hello from Home controller";
return View();
}
}
I am trying to call its action (i.e /Home/Index) but getting 404 Not Found error.
Route registered for other .aspx form are working fine.
routes.Add("Home", new Route("Home", new RoutingHandler("/Default.aspx")));
Everything is working fine but (Home/Index) is not showing up.
You can accomplish this by adding Area in your web project for example MVC. Then you need to register that Area in Global class in Global.asax.cs file's function protected void Application_Start(object sender, EventArgs e) function like below
MVCAreaRegistration.RegisterAllAreas(RouteTable.Routes);
Now add a controller for example Home and add a view say Index. Place a break point on Index action method and run your application. In url type ".../MVC/Home/Index" and the break point will got hit.

Implicit connection of Action Methods with Views in ASP.NET MVC

I am currently working in a brownfield ASP.NET MVC 3 project in VS2010.
In this project, views and controllers are in separate projects. This is not something that I have seen before. In each action method there is no explicit stating of view name as below.
return View("viewName",passingModel);//projects where controllers and views are in same
I have done this implicitly in VS2012 by right clicking on the view and do add view. So I was not bothered about where is this connection between action method's return view and the view is stated.
Unlike in VS2012, in VS2010 I can not navigate to the view that is related to one particular action method by right clicking on View and doing go to view.
I tried to understand this by doing this small experiment. I created a Controller and created a Action Method call xxxx and I created a view for that implicitly as mentioned above and searched the word xxxx in entire solution but this word only appeared in controller and in the view.
So, I was unsuccessful in finding the answer. I think visual studio itself creating its own mapping to achieve this.
I would like to know who these implicit connections are created among action methods and views to understand what is going on in my project.
Edit:
Both the projects which contains controllers and views are class libraries. not asp.net mvc projects.
Global.aspx file contains this:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
protected void Application_Start()
{
DependenciesHelper.Register(new HttpContextWrapper(Context));
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RoutingHelper.RegisterRoutes(RouteTable.Routes);
}
protected void Application_End()
{
//Should close the index
//If this method is not executed, the search engine will still work.
SearchService.CloseIndex();
}
The mapping is fairly straightforward. For example if you have a controller called "MyBrilliantController" and an action method called "MyExcellentAction" which returned just return View(); it would map to (in the UI project) ~/Views/MyBrilliant/MyExcellentAction.cshtml
The only time where this is different is when you are working with "Areas" - but the mapping is effectively the same, it would just consider the area folder first (ie ~/Areas/MyArea/Views/MyBrilliant/MyExcellentAction.cshtml)
Hope that helps.
EDIT - You can also specify namespaces in the global.asax file on each route for the engine to find controllers
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}, // Parameter defaults
new string[] {
// namespaces in which to find controllers for this route
"MySolution.MyControllersLib1.Helpers",
"MySolution.MyControllersLib2.Helpers",
"MySolution.MyControllersLib3.Helpers"
}
);
}

Categories