ASP.NET MVC Routing with child route without Attribute routing - c#

Lets say I want use URL like http://localhost/Controller/1/ChildController/Edit/1 to access the child record(s) of a parent record in ASP.NET MVC 5 project.
Using Attribute Routing we can route like below.
[Route("Controller/{id:int}/ChildController/Edit/{childId:int}")]
public ActionResult EditChildRecord(int id, int childId)
{
return View();
}
How to achieve same in convention-based routing ?
Thanks.

I think what you need it to create a areas.
Create a new area, and set your controllers there. A area will be equivalent to your main controller and the controllers to yours child's controllers.
http://www.tutorialsteacher.com/mvc/area-in-asp.net-mvc

Related

How to Create Custom Routing controller in .net core 2.0

I have a problem, I want to create a specific routing for the controller, as in the example below :
My Controller name= Company
My Action=index
www.mysite.com/CompanyName
you can use [Route()] Annotation top of your controller to set routing for controller. for example if place [Route("api/{controller}")] means that route is controllerName otherwise you can place [Route("api/yourroute")] top of controller for custom routing.
each action has its name for routing. for example for get action method that return list you can place [HttpGet("list")] top of action.

How to add View routing in a .net core project?

I have created a .Net Core Web API program. I want to add a single view to it. Under the same project I add a "Views" folder. In the HomeController, where I am routing all my API requests, I created the following:
[HttpGet("view")]
public IActionResult Index()
{
return View();
}
In my Views folder I created a folder "Home" and added "Index.cshtml" to it.
When I launch the API, and navigate to "../view" I get to the return View(); line, but then it returns a 500 Internal Server Error.
This is what I don't like about the "automagical" approach of MVC convention. I have no idea where to link a view to a controller if the convention didn't work.
Update, this probably should have been my first course of action.
I added a new class to Controllers folder, and used the MVC Controller template in VS2015. I then added a view to match, and it still doesn't work automagically.
So for clarity, my project is: ASP.NET Core Web Application(.NET Core) with a Web API template. I have a "Jobs" controller class that was added at the start as 'Values' and I renamed. Then I added an MVC Controller Class named "HomeController" with the only method being "Index". I added a folder named "Views" and a subfolder named "Home", and added an MVC View Page named "Index.cshtml".
I tried to use "return View();" in the Index method, didn't work. I then tried to add [Route("Home/Index")] above the Index method. Either way, the URL will get me to my break point at "return View();" but it will never return the view.
Note : It's a little strange that you want to return a view in a Web API project, a Web API project is supposed to return some data structure, like json using return new JsonResult(your_json_here) for example.
Note 2 : you need the Microsoft.AspNetCore.Mvc framework (which is installed with the Web API template)
Anyway, you have different ways to configure routing in a asp.net core application :
Creating and extending default routes
Example of routing configuration in the Configure method :
app.UseMvc(routes =>
{
// You can add all the routes you need here
// And the default route :
routes.MapRoute(
name: "default_route",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
});
Using attributes
If you configure routing with attributes, don't forget the controller's one :
Example for the route /index :
[Route("")]
public class HomeController : Controller
{
[HttpGet]
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
Example for the route /home/index :
[Route("[controller]")]
public class HomeController : Controller
{
[HttpGet]
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
Example for the route /iputwhatiwant/actionnameiwant :
[Route("iputwhatiwant")]
public class HomeController : Controller
{
[HttpGet]
[Route("actionnameiwant")]
public IActionResult Index()
{
return View();
}
}
My screen of a .NET Core Web API project returning a view :
For more information, the official documentation is well-documented : https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing
How are you running this webapp, from the Windows commandline?... can you give us the detailed HTTP500 error. It will probably reveal something different than routing errors because that usually gives 404.
[Route("[controller]")]
public class HomeController : Controller
Note the automagical "[controller]" in the Route definition, I think its necessary now
It took me a frustratingly long while to learn the routing convention as it was being developed, but it seems to have normalized out for a few versions. Check out this tutorial documentation on the subject in MVC: Attribute Routing in ASP.NET MVC 5, which is MVC not WebCoreAPI where it is likely based from. If you have a better documentation specific to Web Core API, use that.
This ASP.NET Web Core Build a web API tutorial documentation has some good points about what you seem to be trying to do. Specifically, the section title "Getting to-do items" has this code:
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
{
var item = _todoRepository.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
Looking at that with benefit of some measure of MVC routing experience, it looks particularly different from your approach in that the HTTP verb annotation member property value used is a query parameter.
Seeing I am guessing using known inexpertise, still, I think you need to get the attribute routing fixed, and maybe return an ObjectResult instead of a view, as NightOwl888 suggests. The server error might also have much more useful information along with the exception message.
EDIT: Sorry, I may have misunderstood your question. If you are trying to build an app that serves dynamic web pages instead of a WebAPI that serves data object results, this Build an MVC Web App tutorial, similar to the "Build a web API" tutorial I mentioned before might have your app structure problem answer. If you are trying to do both, you should probably start with the MVC Web App structure or use two separate projects.
The (only) way I have got this working is to declare the path as an attribute on the action - in the same way you have done but with the format as below (Controller/Action):
[HttpGet("Home/Index")]
public IActionResult Index()
{
return View();
}
I was missing:
"preserveCompilationContext": true
in the build options of my project.json

ASP.Net MVC Authentication check on MasterPage

I would like to add a check for Request.IsAuthenticated into my MasterPage (COntroller? Is there such a thing??). Is this possible? I want to redirect to a NoAccess.aspx page if the check fails.
The concept on MVC is different to web forms where you would do common logic on the master.
In ASP.NET MVC master page must only contain UI related setup.
In MVC you use Action filters: decorate your actions with [Authorize].
Did you create a project using the default MVC project template? It has everything you're looking for already in there. If you didn't go ahead and create one now.
Once you're in there you'll notice the [Authorize] attributes as #Aliostad mentioned. These are custom attributes that do the validation on the controller level.
Check out the MVC tutorial on web form security for a more detailed run-down on how it all meshes together: http://www.asp.net/mvc/tutorials/authenticating-users-with-forms-authentication-cs
You can achieve this by creating your own custom authentication attribute.
Create a new filter folder within your project and add the following class
public class NoAccessDirectAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
filterContext.Result = new RedirectResult("noaccess.aspx");
}
}
then decorate your home controller and other required controllers with the Authorization Attribute
[NoAccessDirectAuthorizeAttribute]
public class HomeController : Controller
This will redirect an unathenticated user to your noaccess.aspx page

ASP.NET MVC Routing for Master / Detail Views with "Detail Children"

I have the basic Master / Detail Views working great with the default ASP.NET MVC Route; however I would like to build some URLs like this:
/Class/Details/5 -- General Detail view [Working]
What I'm not sure about (and I'm not tied to this URL format, just something roughly equalivent.)
/Class/5/Details/Logs -- Detail View with Logs
/Class/5/Details/Status -- Detail View with current Status
Another way to put this, is like this:
/{controller}/{id}/{controllerSpecificMaster}/{action}/
What I'm trying to avoid, is cluttering up my Views\Class directory with a bunch of Views, which are all basically derivatives of the Details view.
I'm on ASP.NET MVC 1 and .NET 3.5 SP1.
The first thing you need to get down are your routes. You may have already done this, but in case you haven't, here's a route entry that will handle your custom route needs:
routes.MapRoute("Master_Detail",
"{controller}/{id}/{controllerSpecificMaster}/{action}",
new { controller = "Class",
action = "Index",
id = UrlParameter.Optional,
controllerSpecificMaster = "Details"
});
Then, in your action methods where you want to use the route-specified master page, just include the route key in your method arguments, and then pass it to the view:
public ActionResult Logs(int id, string controllerSpecificMaster)
{
//do something
//return view with master name as argument
return View("Logs", controllerSpecificMaster);
}
If you have to do this a lot, I would suggest creating a custom view engine and override the FindView() method.

Cascading MVC controllers with CatchAll Routes

I have an MVC app which has its routes defined with the final route being a catch all route to a "PageController" for a database driven collection of pages. What I want to achieve is to be able to plugin to the app a second controller to the catch all route which the first controller passes on to if it does not find the url recieved in the database.
Effectively I want to queue up controllers with catch all actions:
public ActionResult PageCatchall(string url)
{
var page = repository.Get<Page>(string url);
if (page != null)
{
// Handle the request
return View(page)
}
// Otherwise pass to a new controller
????
}
Anyone have any good ideas as to how to solve this? I have tried RedirectToAction but that requires that the next controller has a different route to the action. I have tried ActionInvoker but this failed to work the way I did it.
While I would avoid complex routing like this one, I guess best thing to do is to use custom route constraint that uses cached list of pages to match correct route (have done that with success).
I'll leave exact implementation for You as an exercise. ;o)

Categories

Resources