I'm pretty new to MVC and can't find an answer one way or another to this question. Is there a built in architecture in MVC 1 (or 2, I suppose) that allows you to specify a route mapping via an attribute on a specific action method, rather than in the Global.asax? I can see its use being limited to a degree as multiple methods can be tied to the same action thusly requiring routes to be unnecessarily duplicated, but my question still remains.
Also, does anyone see any gotcha's in implementing something like this, aside from the one I just mentioned about the same action on multiple methods?
Note: I'm not asking HOW to implement this. Only checking if something like this exists, and if not, if it's more trouble than it's worth.
You can also try AttributeRouting, which is available via NuGet. Disclosure -- I am the project author. I've used this in personal and professional projects with great success and would not go back to the default routing mechanism of ASP.NET MVC unless I had to. Take a look at the github wiki. There's extensive documentation of the many features there.
Simple usage looks like this:
public class RestfulTestController : Controller
{
[GET("Resources")]
public ActionResult Index()
{
return Content("");
}
[POST("Resources")]
public ActionResult Create()
{
return Content("");
}
[PUT("Resources/{id}")]
public ActionResult Update(int id)
{
return Content("");
}
[DELETE("Resources/{id}")]
public ActionResult Destroy(int id)
{
return Content("");
}
}
AttributeRouting is highly configurable and has a few extension points. Check it out.
I would recommend ASP.NET MVC Attribute Based Route Mapper for this. This is third party library and does not come with ASP.NET MVC 1 or 2. Usage is like the following:
public SiteController : Controller
{
[Url("")]
public ActionResult Home()
{
return View();
}
[Url("about")]
public ActionResult AboutUs()
{
return View();
}
[Url("store/{category?}")]
public ActionResult Products(string category)
{
return View();
}
}
Then in your global.asax, you just call routes.MapRoutes() to register your action routes.
It's dead simple to implement this.
Related
I am wondering if it is possible to do following with ASP.NET MVC 5.
I would like to have a OrderController and the following folder's structure
View/Orders/Details/
I need to know how we can configure methods for Details folder?
I mean Create/Edit/List.
Have we use some method attribute for it or routing and how it should be done?
Thanks!
P.S.
I found very useful this link http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
You have two options. You can either make your own code to determine the correct view to return which is fairly complex or you can specify the view you need using the full path. Additionally if you have to have methods with the same (not sure why you would want that), then you would need to change your routing. An option is to use attribute routing.
public class OrdersController : Controller
{
[Route("CreateOrder")]
public ActionResult Create(Order order)
{
//Snip
return View("~/Views/Orders/Details/Create.cshtml");
}
[Route("CreateOrderDetails")]
public ActionResult Create(OrderDetails orderDetails)
{
//Snip
return View("~/Views/Orders/Details/Create.cshtml");
}
}
Given an ASP.NET MVC Controller class declaration:
public class ItemController : Controller
{
public ActionResult Index()
{
// ...
}
public ActionResult Details()
{
// ...
}
[Authorize(Roles="Admin, Editor")]
public ActionResult Edit()
{
// ...
}
[Authorize(Roles="Admin")]
public ActionResult Delete()
{
// ..
}
}
I need to reflect a list of methods in this class which may be invoked with the current user's permissions.
Please share some ideas of what could be done in this case.
Well for the new question think something along the lines of:
new ReflectedControllerDescriptor(typeof(ItemController)).GetCanonicalActions()
could be used to return the list of all available actions. I don't have ASP.NET MVC available to me at work, so I can't really check to see if the ActionDescriptor's returned by that will contain some parameter which says which members are allowed to execute them.
http://msdn.microsoft.com/en-us/library/system.web.mvc.actiondescriptor_members%28v=VS.90%29.aspx
That is the members of the ActionDescriptor, you might be able to find something in there. I'll see tonight if I can figure it out, this has gotten me kind of intrigued.
There's no universal user login/authentication system for all applications, thus this really isn't possible to create a 'universal solution'. You could create your own user login and authorization classes which you then add your own annotations to methods to do, but its going to have the same restrictions that the asp.net mvc system has, its only for your login/authorization system (or whoever extends that system).
In Visual Studio when you add a new controller to your MVC application some macro creates a file with methods like:
//
// GET: /Thing/Details/5
public ActionResult Details(int id)
{
return View();
}
I want my methods to look like:
/// <example>GET: /Thing/Details/XXX...</example>
public ActionResult Details(Guid id)
{
return View(Repository.GetItem<Thing, Guid>(id, "Id"));
}
The main differences are standard notation for the comments with the two redundant lines removed and I use unique identifiers rather than integers for my id's. If possible, I'd like the code to pass my Model to the view to also be generated.
Is there a built in mechanism that will let me control the code template that is used?
I think David Hayden has a solution for you here. Blog Post
I'm looking at the MVC account controller, and it seems to be from ASP.NET webforms. Is there any good background information on how to use it?
Can you map it to a user database table or is it better to roll your own user management?
How do you make use of it in MVC to restrict what pages a logged in user can view? Do you have to roll all of that on your own?
What resources on the web can help with understanding the ASP.NET Membership?
I'm looking at the MVC account
controller.... it seems to be from
asp.net?
Scott Guthrie explains this quite well in his blog entry about ASP.NET MVC Preview 4. He basically says that the Account Controller from the MVC sample uses the ASP.NET membership provider, so you can use any of those. (I think you can find out more about ASP.NET membership providers on the internet.) If you do not want to implement/use one of those, modifying the application to use your own user management would probably be the best option.
How do you make use of it in MVC to
restrict what pages a logged in user
can view? Do you have to roll all of
that on your own?
You can add the Authorize attribute to the controller class or action method. (Same source as above.)
// Only logged in users can access this controller.
[Authorize]
public class SomeController : Controller
{
#region Not really important for this example. :]
// Maybe rather use a BLL service here instead of the repository from the DAL, but this example is already more verbose than required.
private IStuffRepository stuffRepository;
public SomeController(IStuffRepository stuffRepository)
{
if (null == stuffRepository)
{
throw new ArgumentNullException("stuffRepository");
}
this.stuffRepository = stuffRepository;
}
#endregion
// The authorize attribute is inherited - only logged in users can use the index action.
public ActionResult Index()
{
return View();
}
// Moderators can flag stuff.
[Authorize(Roles="Moderator")]
public ActionResult Flag(int id)
{
this.stuffRepository.Flag(id);
return RedirectToAction("Index");
}
// Admins ans SysOps can delete stuff.
[Authorize(Roles="Admin,SysOp")]
public ActionResult Delete(int id)
{
this.stuffRepository.Delete(id);
return RedirectToAction("Index");
}
// Only joed can change the objects stuff. ;)
// (This is probably bullshit, of course, but I could not make any better example. I blame the fact it is late at night. :))
[Authorize(Users="COMPANY\\joed")]
public ActionResult ChangeId(int oldId, int newId)
{
this.stuffRepository.ChangeId(oldId, newId);
return RedirectToAction("Index");
}
}
If you had to provide a wizard like form entry experience in mvc how would you abstract the page flow?
Investigate the post-redirect-get pattern.
http://weblogs.asp.net/mhawley/archive/tags/MVC/default.aspx
http://devlicio.us/blogs/tim_barcz/archive/2008/08/22/prg-pattern-in-the-asp-net-mvc-framework.aspx
Use that along with a robust domain model (for tracking steps or form completion state or whatever you call it) and you're golden.
In order to keep the steps you could implement a page flow action filters, which provide an experience like this one:
[RequiredStep(FlowStart = true)]
public ActionResult Confirm()
{
return View();
}
[RequiredStep (PreviousStep = "Confirm")]
public ActionResult ExecuteOrder()
{
return RedirectToAction("ThankYou");
}
[RequiredStep(PreviousStep = "ExecuteOrder")]
public ActionResult ThankYou()
{
return View();
}
I left the page flow up to the view, where I believe it belongs, so different views could have different page flows (e.g. for desktop browser clients or mobile phone clients etc.) I wrote it up on my blog: A RESTful Wizard Using ASP.Net MVC… Perhaps?
public class CreateAccountWizardController : Controller
{
public ActionRresult Step1()
{
}
public ActionResult Step2()
{
}
}
There are a couple ways, create an action for each step of the wizard process, or create a parameter that is passed in to the action method. Like step that will allow you to know what the state of the wizard is in.