In MVC5 you could set the default route using the following attribute on a controller?
[Route("{action=index}")]
What is the equivalent of this in MVC6?
Update
This is the code I had in MVC5
[Route("{action=index}")]
public class StaticPagesController : Controller
{
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View();
}
public ActionResult Index()
{
return View();
}
}
I have not been able to work out how to do the equivalent in MVC6 but I've been able to get the same functionality working using the following:
[Route("[action]")]
public class StaticPagesController : Controller
{
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View();
}
[Route("/[action]")]
[Route("/")]
public ActionResult Index()
{
return View();
}
}
You can decorate your specific action method which you want to be the default action with Route attribute and pass [controller] as the route template to that. So anytime you get a request for yoursite/yourcontroller, the incoming request will be redirected to this specific action method.
public class SettingsController : Controller
{
public IActionResult Index()
{
return View();
}
[Route("[controller]")]
public IActionResult OtherIndex()
{
return Content("This will be the response for mySite/Settings request");
}
}
Edit : As per the comment
I don't want to include the controller name in the URL.I want it to be
domain.com/About rather than domain.com/StaticPages/About
Using attribute routing, you can decorate your action method with the Route attribute and give [action] as the template name.
public class StaticPagesController : Controller
{
[Route("[action]")]
public IActionResult About()
{
// This action method will be executed for "yourSite/About" request
return View();
}
}
With the above approach, you cannot have 2 action method's with the same name in your app ( Ex : You cannot have an About action method in HomeController and StaticPagesController)
Related
public class bController : Controller
{
public IActionResult Index(string id)
{
return View();
}
}
I have controller like this. When I want to call index action I need the go to url http://localhost/b/index/id .
But ı want to like this http://localhost/b/id how can i set this action default and call like this. Give me idea pls
Thanks.
If anyone wonder how to do this this is the answer.
public class bController : Controller
{
[Route("b/{id}")]
public IActionResult Index(string id)
{
return View();
}
}
I am trying to route url with and without parameter to two different methods but for some reason it always start first one.
Here is controller code:
public class ProductController : Controller
{
[Route("")]
[Route("Product")] //If i delete this one then it works how it is intended
public IActionResult Index()
{
//It always start this one
....
}
[Route("Product/{GroupID?}")]
public IActionResult Index(int GroupID)
{
....
}
}
I need to share action methods between different controllers. Take for example the following 2 controllers:
public class AController : Controller
{
public ActionResult Index()
{
//print AController - Index
}
public ActionResult Test()
{
//print test
}
}
public class BController : Controller
{
public ActionResult Index()
{
//print BController - Index
}
}
Both controllers have an Index method which is different. The Test method however can be called from both controllers. So I want that when the following urls are entered the Test() method will execute:
AController/Test
BController/Test
I would appreciate any suggestions on how to achieve this.
Assuming the implementation of the Test() action is the same for both controllers, refactor it into a common service:
public interface ITestService {
string Test();
}
public TestService: ITestService {
public string Test() {
// common implementation
return "The test result";
}
}
Then set up Dependency Injection to acquire this service.
Your controllers then can use the common service.
public class AController : Controller {
private readonly ITestService _testService;
public AController(ITestService testservice) {
_testService = testservice;
}
public ActionResult Test() {
var vm = new TestViewModel();
vm.TestResult = _testService.Test();
return View("Test", vm);
}
}
public class BController : Controller {
private readonly ITestService _testService;
public BController(ITestService testservice) {
_testService = testservice;
}
public ActionResult Test() {
var vm = new TestViewModel();
vm.TestResult = _testService.Test();
return View("Test", vm);
}
}
Because the View Test.cshtml is rendered by both controllers, it should be placed in the Views\Shared\ folder.
You can define your own routes as described here: https://learn.microsoft.com/aspnet/core/mvc/controllers/routing
So you can define as many routes as you like to point to the "Test" method inside "AController" just like this:
routes.MapRoute("Atest", "AController/Test",
defaults: new { controller = "AController", action = "Test" });
routes.MapRoute("Btest", "BController/Test",
defaults: new { controller = "AController", action = "Test" });
But you have to define them before the "default" route because otherwise the entered URL will match the default route conditions and so it will enter that route.
It´s also possible to define the route directly in top of the method.
public class AController : Controller
{
[Route("/Some/Route")]
public ActionResult Test()
{
}
}
I want to throw in an alternative solution. Create a base controller class to be inherited by the other two. Whatever you have there will be part of the children.
public class BaseController : Controller
{
public ActionResult Index()
{
//print AController - Index
}
// Add more methods to be shared between the other controllers
}
public class AController : BaseController
{
// Has Index method already from parent
// Unique method for A
public ActionResult Test()
{
//print test 1
}
}
public class BController : BaseController
{
// Has Index method already from parent
// Unique method for B
public ActionResult Test()
{
//print test 2
}
}
This implements the actual functionality in a single place. We use this method for many projects with no issues.
Having Issues trying to throw a 404 error page in MVC 1 from a Controller so that the page actually comes up as page not found. How would I go about doing this?
If you are using MVC1, you may need to create your own HttpNotFoundResult like below and return that from your controller.
public class HttpNotFoundResult : ActionResult {
public HttpNotFoundResult() {
}
public override void ExecuteResult(ControllerContext context) {
context.HttpContext.Response.StatusCode = 404;
}
}
In your action method, you can do.
public ActionResult Index()
{
return new HttpNotFoundResult();
}
From MVC3, you can return HttpNotFound() result directly.
public ActionResult Index()
{
return HttpNotFound();
}
I would add some logic that if your database doesn't return content then return HttpNotFound(); Additionally you can pass a string HttpNotFound("Maybe I deleted it?"); This is very similar to how the WebAPI works.
public ActionResult Index()
{
return HttpNotFound();
}
Suppose I have following Controller and action with authorization Attribute:
public class IndexController : Controller
{
//
// GET: /Index/
[Authorize(Roles="Registered")]
public ActionResult Index()
{
return View();
}
}
I've searched over the entire Internet and not found an answer for this simple question: how to get the roles annotated to an especific Action/Controller? In this case: Index Action has: string[] = {"Registered"}
Finally I found the solution! Was more easy than I thought! ahahha I need extend a class from AuthorizeAttribute and use it in actions. The information I need is the attribute "Roles" of the inherited class:
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var roles = this.Roles;
base.OnAuthorization(filterContext);
}
}
And on Index Controller:
public class IndexController : Controller
{
//
// GET: /Index/
[CustomAuthorizationAttribute(Roles = "Registered")]
public ActionResult Index()
{
return View();
}
}