I searched longer than I care to admit for a solution, but cannot find one.
My site has hundreds of static pages.
It is very tedious to add a single ActionResult per View.
Especially because I have to stop debugging to edit the code.
So for example, if I want to add an About page I have to add...
public ActionResult About()
{
return View();
}
It seems to me that I should be able to make this dynamic and pass the view in via the route.
I mean, as long as I have a file called About.cshtml, then why do I need to add a custom ActionResult.
I'd rather do something like this, but it doesn't work.
public ActionResult Index(_ViewName)
{
return View(_ViewName);
}
Is it possible to have a generic ActionResult and pass the name of the view in via the URL Route?
With your default route you can edit index method as below and get it done.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
public ActionResult Index(string id)
{
return View(id);
}
What you have to do is add the view according to the name you are parsing.
Example
/home/index/about
/home/index/contact
(About.cshtml and Contact.cshtml views should be in /Views/Home/ folder)
Thanks!
Related
My application has a custom route that looks like this:
routes.MapRoute(
name: "ProjectDocument",
url: "Project/{projectid}/{controller}/{action}/{id}",
defaults: new { controller = "Document", action = "Index", projectid = 0, id = UrlParameter.Optional }
);
Basically, there are multiple projects and each project can have documents. The documents may have the same id so I need the combination of projectid and documentid to get the correct document.
I've created an Edit view ("/Project/101/Document/Edit/78"). When the user posts the form, I first check the ModelState in my "Document" controller. If that fails, I want to return the model/modelstate to the view to show the errors. With normal routing, I would just use
if (!ModelState.IsValid)
{
return View(model);
}
but this doesn't work with the custom route because it returns "Document/Edit/78" (without the custom routing).
Can someone point me in the right direction for how I would return the full custom route on that error?
Thanks
UPDATED PER REQUEST
In my Documents Controller
GET
public async Task<ActionResult> Edit(int projectid, int id)
{
...
POST
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ProjectDocument projectdocument)
{
...
I figured it out. I had my new route below the Default route in my RouteConfig.cs file. Thanks to Stephen for pushing me to look a bit further into other parts of my code.
I'm just starting out with .NET, and am building a test application. I currently have the homepage set using a DefaultController, and an Index() action method. This works as expected, and the homepage is simple www.domain.com.
I have created 2 new pages (Terms and Privacy) under the same DefaultController, using Terms() and Privacy() action methods.
I want to be able to browse to these with the URL as www.domain.com/terms and www.domain.com/privacy.
When i use a <li>#Html.ActionLink("Terms of Service", "Terms", "Default")</li> it works, but it takes me to the URL at www.domain.com/Default/privacy.
Should i be creating seperate controllers for each of these pages, or am I using the #html.ActionLink helper incorrectly? I have previously used <li>Privacy Policy</li> but I understand this isn't best practice?
Also, is there a way to force links as lowercase?
My Controller Code:
public class DefaultController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Terms()
{
return View();
}
public ActionResult Privacy()
{
return View();
}
}
If these were in the HomeController I don't believe you'd have the same problem. However, I think you can get around this by using the RouteConfig file:
routes.MapRoute(
name: "Default",
url: "{Action}/{Id}",
defaults: new { controller = "Default", Action = "Index", Id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Generic",
url: "{controller}/{Action}/{Id}",
defaults: new { Action = "Index", Id = UrlParameter.Optional }
);
I believe that what you want to do is hide the controller name in the url. If that is the case, your question is answered here:
ASP.NET MVC - Removing controller name from URL
You can use Attribute routing to give specific routes to endpoints.
[Route("terms")]
public ActionResult Terms()
{
return View();
}
[Route("privacy")]
public ActionResult Privacy()
{
return View();
}
In your RouteConfig.cs you must enable attribute routing with the following line of code: routes.MapMvcAttributeRoutes();
Now any urls generated with #Url.Action() or #Html.ActionLink should generate URLS as domain.com/privacy and domain.com/terms
This issue has been discussed many times, but I haven't found a resolution for my particular case.
In one of my Umbraco (6) views I am calling a controller method by using
#Html.Action("Index", "CountryListing");
This results in the "no route in the route table" exception.
I have been fiddling around with the RegisterRoutes method to no avail. I wonder if it is even used as the site still functions when I empty the RegisterRoutes method. This is what it looks like now:
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 }
);
}
I have also tried adding an empty "area" to the call like this
#Html.Action("Index", "CountryListing", new {area: String.Empty});
I am using #Html.Action statements in other places and they DO work, so I do understand why some of them work and others don't, but the main problem now is getting my country listing action to work.
You can solve this by doing the following
Make sure your Controller is extending Umbraco's SurfaceController
Name it YourName*SurfaceController*
Add the [PluginController("CLC")] 'annotation' (I am from Java) to your controller. CLC stands for CountryListController. You can make up your own name of course.
Add the PluginController name (CLC) to the Html.Action call as a "Area" parameter.
My controller:
[PluginController("CLC")]
public class CountryListingSurfaceController : SurfaceController
{
public ActionResult Index()
{
var listing = new CountryListingModel();
// Do stuff here to fill the CountryListingModel
return PartialView("CountryListing", listing);
}
}
My partial view (CountryListing.cshtml):
#inherits UmbracoViewPage<PatentVista.Models.CountryListingModel>
#foreach (var country in Model.Countries)
{
<span>More razor code here</span>
}
The Action call:
#Html.Action("Index", "CountryListingSurface", new {Area= "CLC"})
you can use null instead of using String.empty
#Html.Action("Index", "CountryListing",null);
if you are using area, you have to override RegisterRoutes for every area
public override string AreaName
{
get
{
return "CountryListing";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"CountryListing_default",
"CountryListing/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
and i recommend you take a look at the same problem:
https://stackoverflow.com/a/11970111/2543986
So i'm trying to employ the use of hyphens in my URLs for readability but so far haven't found a way to make it work with mvc4.
I'll start with the code in the controller:
public ViewResult Index()
{
ViewBag.URL = Functions.fetchURL();
return View();
}
[HttpPost]
public ActionResult Index(LogonModel model, string returnUrl)
{
//omitted to save space
return View(model);
}
public ActionResult Forgot_Login_Info()
{
return View();
}
[HttpPost]
public ActionResult Forgot_Login_Info(RetrievePasswordViewModel model)
{
//omitted to save space
return View();
}
So I'm using underscores for the name of the actions as seen with "Forgot_Login_Info" and that is the name of the view as well. For testing I also manually created a view called "Forgot-Login-Info"
In my global.asax.cs file i simply have this line for routes
RouteConfig.RegisterRoutes(RouteTable.Routes);
which is the standard routing line with new projects for MVC4 and this is hooked to the "RouteConfig.cs" file and in that file here is the code I have, which I found in another question on this site.
public class RouteConfig
{
public class HyphenatedRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["controller"] = requestContext.RouteData.Values["controller"].ToString().Replace("-","_");
requestContext.RouteData.Values["action"] = requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
return base.GetHttpHandler(requestContext);
}
}
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 }
);
routes.Add(
new Route("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Default", action = "Index", id = UrlParameter.Optional }),
new HyphenatedRouteHandler())
);
}
}
Lastly here is the code for the "Index" view, which is where I have a link to the "Forgot_Login_Info".
<div class="centerBlockItem" style="width:450px; text-align:center">
#Html.ActionLink("Forgot Password?", "Forgot-Login-Info")
#Html.ActionLink("Forgot Password?", "Forgot_Login_Info")
</div>
Now I have the link 2 ways, 1 using underscore and the other using hyphen. According to what i've read in regards to the code I found for this purpose, Both links should open the "Forgot_Login_Info" view and not the "Forgot-Login-Info" view. But what I'm getting instead is the 2nd link works fine and the action name matches the view files name. But when I click on the first link, I get a 404 error because the system can't find the "Forgot-Login-Info" view file, even though I had manually created a file with that name for testing.
One more thing to note, the code in my routeconfig file, In the answer I had found it suggested I comment out the default route code lines and just leave:
routes.Add(
new Route("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Default", action = "Index", id = UrlParameter.Optional }),
new HyphenatedRouteHandler())
);
I had done this too and got the same results. Any ideas where I'm screwing things up?
Ok I figured out what I was doing wrong, I had this listed under the root routebundle.cs file but i was trying to make this work in an area, once I moved this code to the area registration file, it worked like a charm. If anyone needs my full code listing just ask and i'll post it all up.
How is this helping SEO when the crawlers can still access the underscore version of the controller, thereby duplicating content. Struggling with this right now.
I'm very new to MVC, and am attempting to add further functionality to an app that has already been developed.
I'm having trouble returning a View with posted results after validation has rendered the model invalid.
My controller has three actions of note:
public ActionResult Create(int workID)
[HttpParamAction]
[HttpPost]
public ActionResult SaveNormal(WorkViewModel workView)
[HttpParamAction]
[HttpPost]
public ActionResult SaveAddAnother(WorkViewModel workView)
Because of previous requirement, I've had to change the submit action so that one of the two above are called with the posted results. Everything works fine except is I'm trying to post back due to the model state being invalid, which I'm attempting to with the following:
if (!ModelState.IsValid)
return View("Create", workView);
It does take me to the create (Create.aspx) view, but the URL is Work/Action, rather than Work/Create, meaning that when I resave, Work/Action is not found.
I'm not sure if this is a routing issue, but have supplied routes below (which are basically the default I think...):
public static void RegisterRoutes(RouteCollection routes)
{
// This is the original
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
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
Any help will be much appreciated!
the URL is based on the action name; not on the view name. You probably need to RedirectToAction("Create"...) and issue View() from there