I have a controller located in Controllers folder.
Controllers
.... CustomViewController
The CustomViewController executes the following method
public ActionResult DisplayPerson()
{
Person prn = new Person();
prn.Name = "Rama";
prn.Email = "Jass#yahoo.com";
return View(prn);
}
I have two views located in CustomView folder
Views
....CustomView
.. DisplayPerson
.. PersonView2
Routing
routes.MapRoute(
"Display",
"{Controller}/{action}/{id}",
new { controller = "CustomView",
action = "DisplayPerson", id = "" }
);
Question :
By default the view "DisplayPerson" is used to display the Person details.What is the
way to call the view "PersonView2" inside the "DisplayPerson()" method.
return View("DisplayPerson", prn)
or
return View("PersonView2", prn)
http://msdn.microsoft.com/en-us/library/dd460310.aspx
Related
We all know url in ASP.NET MVC always like example.com/controller/action?param1=value1¶m2=value2
I'd like to know is there a way to put action name in query string just like example.com/controller?aciton=index¶m1=value1¶m2=value2(notice action=index in query string), and make ASP.NET MVC route the url to the corresponding controller and action. The name of the query name can be action or something else.
--- update 28th Sep ---
The actual situation is I have a form, inside the form is a table with radio button each column and some button (create, edit, delete etc.) above the table. These buttons go to different action in same controller.
As a result of search, I've got some solutions:
handle onsubmit via JavaScript and change the action property of form. Answer link
write a "route" method in controller to re-route the request. Answer link ( I think this is not a graceful solution )
write a custom attribute let ASP.NET MVC route to corresponding action base on query. This anwser and this answer ( Very close to my original idea, I am currently using this solution )
I'm the questioner and just several hours after I update the question, I finally figure out the solution. That is write a custom Route.
public class QueryActionRoute : Route
{
public QueryActionRoute(string url, object defaults) : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler()) { }
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var routeData = base.GetRouteData(httpContext);
var action = httpContext.Request["action"];
if (routeData != null)
{
if (!string.IsNullOrEmpty(action))
{
routeData.Values["action"] = action;
}
}
else
{
routeData = new RouteData()
{
Values = { {"action", "Index"} }
};
}
return routeData;
}
}
and replace the default route
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(
"Default",
new QueryActionRoute(
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }));
}
}
after that you can access an action via
example.com/home/about?param=value(you can emit action name if the action is "index") like before
or
example.com/home?action=about¶m=value.
I's really helpful when you need to specify different buttons to go different actions in form. You can make it in this way:
<form action="#Url.Action("Index")">
<button name="action" value="Create">Create</button>
<button name="action" value="Details">Detail</button>
<button name="action" value="Edit">Edit</button>
<button name="action" value="Delete">Delete</button>
</form>
I have problem with create ulr routing for asp.net mvc3 application.
My project has this structure :
Areas
EmployeeReport
Controllers
Report
Views
Report
List
....
Controllers
Login
Viwes
Login
...
EmployeeReportAreaRegistration.cs :
public class EmployeeReportAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "EmployeeReport";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
var routes = context.Routes;
routes.MapRoute(null, "vykazy/vykazy-zamestnance", new { Area = "EmployeeReport", controller = "Report", action = "List" });
}
}
Global.asax :
routes.MapRoute(null, "prihlasit", new { controller = "Login", action = "Login" });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Default", action = "Welcome", id = UrlParameter.Optional });
When i try load "http://localhost/app_name/vykazy/vykazy-zamestnance
i get this exception :
The view 'List' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Report/List.aspx
~/Views/Report/List.ascx
~/Views/Shared/List.aspx
~/Views/Shared/List.ascx
~/Views/Report/List.cshtml
~/Views/Report/List.vbhtml
~/Views/Shared/List.cshtml
~/Views/Shared/List.vbhtml
Well, where I do mistake ?
Thanks
revised answer:
Adding to Context.Routes directly means it loses any information about Areas.
Either use AreaRegistration.MapRoute (which is overriden to put in the Area information).
context.MapRoute(...);
Or put the area in the DataTokens parameter (not the defaults parameter as you have done here)
context.Routes.MapRoute("", "url", new {...}, null, new {area = this.AreaName});
Your folder structure for your area should look like so:
Areas
EmployeeReport
Controllers
Views
I am doing some plugin kind of work using asp.net mvc.
I have two plugins(mvc projects) Say users and home. In both the plugins, I have Home Controllers. Yes the names are home controller in both the plugins(projects). When I build the project the Dlls are copied to the host project (third one).
this is home plugin
namespace Plugin.Home.Controllers
{
public class HomeController : Controller
{
public string Index()
{
return "Home from home";
}
public string JustATest()
{
return "Just a test from home";
}
}
}
Here is another controller in different project(User Plugin)
this is home controller
namespace Plugin.Users.Controllers
{
public class HomeController : Controller
{
public string Index()
{
return "Home from Users";
}
public string JustATest()
{
return "Just a test from Users";
}
public string JustAnotherTest()
{
return "Just another test from Users";
}
}
}
In global.asax I have register routes using namespaces.
routes.MapRoute(
"Default", // Route name
"Home/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "Plugin.Home.Controllers" }
routes.MapRoute(
"Users", // Route name
"users/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "Plugin.Users.Controllers" }
);
I can access all the routes in the browser without any problem.
Now the problems
I try to use #{Html.RenderAction("JustATest","Home");}
It only renders from the home controller in home module. How can i render it from Users module.
It throws an exception saying method not found in home controller,
when I say #{Html.RenderAction("JustAnotherTest","Home");}
At what stage I can check if a given controller has the given method or not (Some ControllerFactory). Or how can i make sure it picks up the right controller.
Help will be appreciated.
Regards
Parminder
If you really need to save controller names both HomeController, i see simple solution to use hack like this:
routes.MapRoute(
null,
"{home}/{action}/{id}",
new { controller = "Home", action = "Index", home="Home", id = UrlParameter.Optional });
routes.MapRoute(
null,
"{home}/{action}/{id}",
new { controller = "Home", action = "Index", home="Users", id = UrlParameter.Optional }
);
And you can access to this actions both by url and with RenderAction:
#{Html.RenderAction("JustATest","Home", new {home="Home"});}
#{Html.RenderAction("JustATest","Home", new home="Users");}
But I think that problem is artificial (because it is more hard that you imagine), and you use means only for using means, but not for solving real problem. For real plugin architecture you need to create at least:
1. Custom Route Constraint for checking, that controller type is from assembly, where controller was defined.
2. Installer, that will install all routes independently of main application
3. Create unit tests for each plugin application Routes to ensure that all routes, that was installed from plugins, that do not know anything about each other, works properly (and don't break each other).
I recommend to take your controllers at main web application and give them different names.
See the format used here:
render action with lambda
#Html.RenderACtion<Plugin.Home.Controllers.HomeController>(...)
Edit
I see your issue now. It's that they are dynamically loaded at runtime and hence the names aren't known when you compile. Check out using DefaultControllerFactory as mentioned in various postings here:
How to achieve a dynamic controller and action method in ASP.NET MVC?
i have a static website (no database) and am having difficulty understanding how to setup routes for sub-categories. for example, i can do the following where the category is the controller and the make is the action:
cars/toyota
cars/bwm
but when i add another level i don't know how to setup the route
cars/toyota/camry
cars/toyota/corolla
cars/toyota/celica
I'd probably go with year/make/model
routes.MapRoute(
"Default",
"{controller}/{year}/{make}/{model}"
new
{
controller = "car",
action = "search",
year = DateTime.Today.Year,
model = "all",
make = Url.OptionalParameter
}
);
(you might want a constraint on the year to force it to be a reasonable value?)
with a controller like
public class CarController
{
public ActionResult Search( int year, string make, string model )
{
// handle model "all" and empty "make" specially
}
}
You should be ok with a route looking like this:
routes.MapRoute(
"CarsRoute",
"cars/{make}/{model}",
new {
controller = "Cars",
action = "Display",
make = UrlParameter.Optional,
model = UrlParameter.Optional
});
This would map to an action method with the signature:
public ActionResult Display(string make, string model)
Where both make and model can be null. You can then perform your actions.
I am working on a very simple application, using MVC2 Preview 1.
I have a controller named ContentController. My problem is that /Content/Index works correctly, but /Content/ returns a 404. I am running the application on the Studio Development Server.
Tested with RouteDebugger but /Content/ returns a 404, and does not display any debugging information.
I have not changed the routing code:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
This is my controller:
public class ContentController : Controller
{
IRepository _repo = new SimpleRepository("db", SimpleRepositoryOptions.RunMigrations);
public ActionResult Index()
{
var content = _repo.GetPaged<Content>(0, 20);
return View(content);
}
It's a shot in the dark, but do you have a directory named /Content/ as well?
/Content is a controller, which is basically just a collection of actions. ASP.NET MVC needs to know WHICH action you want to run, so by leaving out the action asp.net mvc doesn't know what action to return and gives a 404.
You can tell it a default either by adding a route:
eg:
routes.MapRoute("ContentDefault", "Content", new {controller = "Content", action = "Index"});
The attributes are defined as follows:
'ContentDefault`: Name of the Route (must be unique in your routing table)
Content: The URL segment (try changing this to 'Content/Much/Longer/URL' and then go to http://localhost/Content/Much/Longer/URL to see how this works)
new {controller=.., action=...}: which controller/action combo to run for this route.
You could also override HandleUnknownAction in your controller:
protected override void HandleUnknownAction(string actionName)
{
return RedirectToAction("index");
}
Oh and incidentally, an extra piece of advice about routing.... if you add something to the route in braces { } these will be passed to the action as an attribute.
e.g. /Content/Much/Longer/Url/{page}
so the URL http://localhost/Content/Much/Longer/Url/999
will pass the 999 into your action, as the page attribute
public ActionResult Index(int Page) { }
I love MVC - never going back to WebForms - this is how web development should be!