is there any possibility to create a maproute which would use always one method and it won't be necessary to put it in address?
I mean I've got controller with one method (Index) and it displays items depend on methods argument.
public ActionResult Index(string TabName)
{
var tab = (from t in BlogDB.Tabs
where t.TabName == TabName
select t).SingleOrDefault();
ViewData.Model =(Tab)tab;
return View();
}
and what I want is that I can display items putting address "www.example.com/Tabs/TabName" without "/Index/" between Tabs and TabName. I've tried:
routes.MapRoute(
"Tabs1",
"Tabs/{TabName}",
new { controller = "Tabs", action = "Index", TabName = UrlParameter.Optional }
);
But it doesn't work.
do you still have the default route? and if yes is it defined before this one?
Your problem is that asp.net mvc is trying to find the Tabs controller and the Tabname action.
Put this route before the default {controller}/{action} route
Related
I am working on a ASP.Net MVC project. I have a particular controller action that accepts a date value in the form yyyy/mm/dd. So the URL becomes
http://localhost/MyProject/PublicReview/GetReviews/2012/10/29.
where GetReviews is an action and 2012/10/29 the parameter.
My RouteConfig is as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
How should I change the routevalues ? What should be the order of MapRoute values?
I've not tested this, but I'm guessing this will work in your scenario:
routes.MapRoute(
"Reviews", "PublicReview/GetReviews/{year}/{month}/{day}"
{ controller = "PublicReview", action = "GetReviews" };
Note that this will need your GetReviews method to have three properties of "year", "month" and "day". You'll then have to parse them into a DateTime.
Taken from http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-custom-routes-cs which uses "-" for date separators.
I am working on an ASP.Net MVC 3 RC project. I have one area named Drivers. I have a LoadPartial() action in a controller in the Drivers area that returns a PartialView(string, object); When this is returned I get an error on my webpage that says "The partial view 'PublicAttendanceCode' was not found." It searched the following locations:
~/Views/AttendanceEvent/PublicAttendanceCode.aspx
~/Views/AttendanceEvent/PublicAttendanceCode.ascx
~/Views/Shared/PublicAttendanceCode.aspx
~/Views/Shared/PublicAttendanceCode.ascx
~/Views/AttendanceEvent/PublicAttendanceCode.cshtml
~/Views/AttendanceEvent/PublicAttendanceCode.vbhtml
~/Views/Shared/PublicAttendanceCode.cshtml
~/Views/Shared/PublicAttendanceCode.vbhtml
Why is it not searching in the Drivers Area?
I have the following pretty basic routes in Global.asax.cs:
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
}
);
}
And in DriversAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Drivers_default",
"Drivers/{controller}/{action}/{id}",
new { action = "RequestLeave", id = UrlParameter.Optional }
);
}
What am I missing that will make it look in the drivers area for the partial?
How are you providing area name to PartialView() method? I think you should be passing it in new { area = "Drivers" } as routeValues parameter.
The way that the MVC view engines know the area that they should look in is based on the route that was used to process the request.
In the case of the controller action that you have, are you certain that the request was processed by the area's route definition, or is it possible that the request was processed by the more general route that you defined in global.asax?
There are only four overloads of the method PartialView and it seems like neither of them accept routeValues as a parameter.
I solved this problem like this:
return PartialView(
VirtualPathUtility.ToAbsolute("~/Areas/MyArea/Views/Shared/MyView.cshtml"));
It works, but looks ugly.
This works too:
return PartialView("~/Areas/Admin/Views/Shared/MyView.cshtml", model);
I have the following route ( it's the first in my global.asax )
routes.MapRoute(
"AdminCompany", // Route name
"{controller}.aspx/{action}/{companyId}/{id}", // URL with parameters
new { controller = "Home", action = "Index", companyId = "", id = "" } // Parameter defaults
);
if i navigation to
"Order/DisplayAdmin/2/79000180" it resolves correctly
However if i do the following
Html.ActionLink("View", "DisplayAdmin", new {companyId = Model.CompanyId, id = order.OrderNumber }, new { #class = "button add" })
it displays
/Order.aspx/DisplayAdmin/39068760?companyId=0
which also works, but isn't so pretty :)
Here is my Controller Method
public ActionResult DisplayAdmin(int companyId, [DefaultValue(0)]int id, [DefaultValue(0)] int orderItemStatusId)
{
var viewModel = DisplayAdminViewModel(companyId, id, _statusResponses);
return View(viewModel);
}
Am i calling ActionLink the wrong way? how do i get the nice Urls?
only thing I can think of that is happening is that its falling back to the Default route, I did a copy paste of both your route and the html.ActionLink and it works perfectly for me displaying it like "/Order.aspx/DisplayAdmin/39068760/45456", i did replicate the same fault like you get if the naming isn't the same in the route and action link.
Use the overload of ActionLink that has a RouteValueDictionary argument.
It appears that you are currently using the overload with the "object" argument and it's going to a workable, but not as clean, url.
We're building a site that will have very minimal code, it's mostly just going to be a bunch of static pages served up. I know over time that will change and we'll want to swap in more dynamic information, so I've decided to go ahead and build a web application using ASP.NET MVC2 and the Spark view engine. There will be a couple of controllers that will have to do actual work (like in the /products area), but most of it will be static.
I want my designer to be able to build and modify the site without having to ask me to write a new controller or route every time they decide to add or move a page. So if he wants to add a "http://example.com/News" page he can just create a "News" folder under Views and put an index.spark page within it. Then later if he decides he wants a /News/Community page, he can drop a community.spark file within that folder and have it work.
I'm able to have a view without a specific action by making my controllers override HandleUnknownAction, but I still have to create a controller for each of these folders. It seems silly to have to add an empty controller and recompile every time they decide to add an area to the site.
Is there any way to make this easier, so I only have to write a controller and recompile if there's actual logic to be done? Some sort of "master" controller that will handle any requests where there was no specific controller defined?
You will have to write a route mapping for actual controller/actions and make sure the default has index as an action and the id is "catchall" and this will do it!
public class MvcApplication : System.Web.HttpApplication {
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 = "catchall" } // Parameter defaults
);
}
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new CatchallControllerFactory());
}
}
public class CatchallController : Controller
{
public string PageName { get; set; }
//
// GET: /Catchall/
public ActionResult Index()
{
return View(PageName);
}
}
public class CatchallControllerFactory : IControllerFactory {
#region IControllerFactory Members
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
if (requestContext.RouteData.Values["controller"].ToString() == "catchall") {
DefaultControllerFactory factory = new DefaultControllerFactory();
return factory.CreateController(requestContext, controllerName);
}
else {
CatchallController controller = new CatchallController();
controller.PageName = requestContext.RouteData.Values["action"].ToString();
return controller;
}
}
public void ReleaseController(IController controller) {
if (controller is IDisposable)
((IDisposable)controller).Dispose();
}
#endregion
}
This link might be help,
If you create cshtml in View\Public directory, It will appears on Web site with same name. I added also 404 page.
[HandleError]
public class PublicController : Controller
{
protected override void HandleUnknownAction(string actionName)
{
try
{
this.View(actionName).ExecuteResult(this.ControllerContext);
}
catch
{
this.View("404").ExecuteResult(this.ControllerContext);
}
}
}
Couldn't you create a separate controller for all the static pages and redirect everything (other than the actual controllers which do work) to it using MVC Routes, and include the path parameters? Then in that controller you could have logic to display the correct view based on the folder/path parameter sent to it by the routes.
Allthough I don't know the spark view engine handles things, does it have to compile the views? I'm really not sure.
Reflecting on Paul's answer. I'm not using any special view engines, but here is what I do:
1) Create a PublicController.cs.
// GET: /Public/
[AllowAnonymous]
public ActionResult Index(string name = "")
{
ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);
// check if view name requested is not found
if (result == null || result.View == null)
{
return new HttpNotFoundResult();
}
// otherwise just return the view
return View(name);
}
2) Then create a Public directory in the Views folder, and put all of your views there that you want to be public. I personally needed this because I never knew if the client wanted to create more pages without having to recompile the code.
3) Then modify RouteConfig.cs to redirect to the Public/Index action.
routes.MapRoute(
name: "Public",
url: "{name}.cshtml", // your name will be the name of the view in the Public folder
defaults: new { controller = "Public", action = "Index" }
);
4) Then just reference it from your views like this:
YourPublicPage <!-- and this will point to Public/YourPublicPage.cshtml because of the routing we set up in step 3 -->
Not sure if this is any better than using a factory pattern, but it seems to me the easiest to implement and to understand.
I think you can create your own controller factory that will always instantiate the same controller class.
I am trying to build a small ASP.NET MVC 2 application.I have a controller class with the below method in it
public ActionResult Index()
{
TestMvc.Models.PersonalInformation objPerson = new TestMvc.Models.PersonalInformation();
objPerson.FirstName = "Shyju";
objPerson.LastName = "K";
objPerson.EmailId="shyju#company.com";
return View(objPerson);
}
And when the page (View) being called, i can see this data there as my view has these data's displaying. Now i want to know how can i pass a query string in the url and use that id to build the PersonalInformation object.Hoe can i read the querystring value ? Where to read ?
I want the quesrtstring to be like
http://www.sitename/user/4234 where 4234 is the user id
http://www.sitename/user/4234 is not a querystring. The querystring is the part of the URL that comes after the ?, as in http://www.sitename/user?userId=42
However, the default routes that come with the MVC project template should allow you to simply change the signature of your action method to
public ActionResult Index(int id)
and you should get the desired result. You should look into how routing works in MVC if you want full control of your URLs.
Also, note that the index action is usually used for showing a list of all objects, so you probably want the Details action for showing 1 user object.
What you want is to modify your action to accept an id like so:
public ActionResult Index(string id)
{
TestMvc.Models.PersonalInformation objPerson = new TestMvc.Models.PersonalInformation();
if (!string.isNullOrEmpty(id))
{
objPerson = getPerson(id);
}
return View(objPerson);
}
Then add a route to your global.asax:
routes.MapRoute(
"MyRoute", // Route name
"user/{id}", // URL with parameters
new { controller = "mycontroller", action = "index", id = ""} // Parameter defaults
);