MVC return view() issue - asp.net-mvc

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

Related

Same route parameters with different controllers' action methods causes an error in Asp .Net MVC

I m using attribute routing feature of Asp .Net Mvc.
My first action is like below which is placed in SurveyController
[Route("{surveyName}")]
public ActionResult SurveyIndex()
{
return View();
}
And my second action is like below which is placed in MainCategoryController
[Route("{categoryUrlKey}")]
public ActionResult Index(string categoryUrlKey)
{
return View();
}
I'm not using convention based routing.
Below is my RouteConfig.
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.MapAttributeRoutes();
}
Now the problem is when i click to a survey it redirects to the MainCategory/Index route. I know it is because of same route pattern but i cant change this into another thing.
how can I handle this situation?
Thanks
You should prefix the routes on your MainCaregoryController, either at the controller level like this:
[RoutePrefix("category")]
public class MainCategoryController : Controller {
or at the action level like this:
[Route("category/{categoryUrlKey}")]
public ActionResult Index(string categoryUrlKey)
{
return View();
}
Routes should not clash. This route:
[Route("{categoryUrlKey}")]
public ActionResult Index(string categoryUrlKey)
{
return View();
}
matches any string and passes that string value into the action, so without a prefix it will match:
http://localhost/validcategorykey
and
http://localhost/something/id/isthispointmakingsense
and your categoryUrlKey parameter would equal "validcategorykey" in the first instance and "something/id/isthispointmakingsense" in the second.
Now as for this route:
[Route("{surveyName}")]
public ActionResult SurveyIndex()
{
return View();
}
This just won't work period. This needs to be changed to:
[Route("survey/{surveyName}")]
public ActionResult SurveyIndex(string surveyName)
{
return View();
}

MVC5 Url.Action not returning correct URL

I'm trying to use a Kendo Grid for a list of objects on my model, but the url's generated by the .Create() etc. methods are not generating the url correctly.
It doesn't appear to be just Kendo though because even in my controller using Url.Action() generates the wrong url.
// POST: Assessment/Create
[HttpPost]
[ValidateAntiForgeryToken]
[Route("eForms/Assessment/Create")] // <-- Tried with and without this
public ActionResult Create(AssessmentPoco model)
{
var x = Url.Action(("Allergy_Read", "Assessment");
}
//POST: Assessment/Allergy_Read
[HttpPost, ActionName("Allergy_Read")]
[Route("AllergyRead", Name = "Allergy_Read")]
public ActionResult Allergy_Read([DataSourceRequest] DataSourceRequest request, AssessmentAllergiesSection model) //, int id)
{
return Json(new[] { model }.ToDataSourceResult(request, ModelState));
}
Expected: eForms/Assessment/Allergy_Read
Actual: /?action=Allergy_Read&controller=Assessment
Route config:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//web forms default
routes.MapPageRoute(
routeName: "WebFormDefault",
routeUrl: "",
physicalFile:"~/default.aspx");
routes.MapRoute(
name: "API",
url: "eforms/api/{controller}/{action}/{id}",
defaults: new {controller="Customer", action="GetCustomers", id = UrlParameter.Optional}
);
////mvc default
routes.MapRoute(
name: "Default",
url: "eforms/{controller}/{action}/{id}",
defaults: new { controller = "IncidentReports", action = "Search", id = UrlParameter.Optional }
);
}
Not sure what else could be at fault here (besides my brain), any ideas?
Clarifications (from comments):
We are using Areas
Global.asax is calling RegisterRoutes (also tried turning it off no change)
Update:
This project is a newly added MVC project to an existing ASP.Net WebForms app. I updated the Route config because I was using looking at the wrong one.
You're using routeAttribute, so put a name inside it and use Html.RouteLink or Url.RouteUrl instead of Url.Action().
Example:
[Route("menu", Name = "mainmenu")]
public ActionResult MainMenu() { ... }
Usage in View:
Main menu
I tried this code in controller:
public class HomeController : Controller
{
[Route("AllergyRead", Name = "Allergy_Read")]
public ActionResult Allergy_Read()
{
return View();
}
}
And:
#Html.RouteLink("Allergy Read", "Allergy_Read")
Give me the right route to action. I can't figure out why your implementation isn't working.

MVC5 use single ActionResult for multiple pages?

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!

Html.Action() results in "No route in the route table matches the supplied values"

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

MVC4 hyphen in URL

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.

Resources