Can Asp.Net Mvc Route Constraints throw a 404 instead of InvalidOperationException? - asp.net-mvc

I'm trying to use route constraints in an Asp.Net MVC Application.
routes.MapRoute(
"theRoute",
"MyAction/{page}",
new { controller = "TheController", action = "MyAction", page = 1 },
new { page = #"[0-9]" });
When I enter an url like ~/MyAction/aString, an YSOD is shown with an invalid operation exception. What can I do to redirect invalid url to the 404 page?
I know I can solve the issue with a string parameter in the controller action and int.TryParse, but then the route constaint is useless.
How can I choose the exceptiontype that is thrown by the route constraints?

The problem is that you do not have a route that matches the route that ends in a string.
Modify your routes similar to:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = 0 },
new { id = "[0-9]" }// Parameter defaults
);
routes.MapRoute(
"Default2", // Route name
"{controller}/{action2}/{sid}", // URL with parameters
new { controller = "Home", action = "Index2", sid = "" } // Parameter defaults
);
and modify your controller
public ActionResult Index(int id)
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC! Your id is: "+ id.ToString();
return View();
}
public ActionResult Index2(string sid)
{
ViewData["Title"] = "Home Page 2."+sid.ToString();
ViewData["Message"] = "Welcome to ASP.NET MVC! \"" + sid.ToString() +"\" is an invalid id";
return View("index");
}
now when you pass a string for the ID, Index2 will be called and you can do whatever you need to do to handle the incorrect parameter.

Just to mention a more general redirection:
You can write in the Web.config of your application:
<system.web>
...
...
<customErrors mode="On">
<error
statusCode="404"
redirect="/Home/MyCustomError" />
<!-- Is not necessary that the
view MyCustomError.aspx are inside the
Home folder, you can put that
view in the Shared folder.
-->
</customErrors>
...
...
</system.web>
Then you need to have an ActionResult called MyCustomError
public class HomeController : Controller
{
...
...
public ActionResult MyCustomError(string aspxerrorpath)
/* the var aspxerrorpath
* is that MVC generated by
* default */
{
ViewData["messageError"] = aspxerrorpath;
return View();
}
}
Then you can make a custom error page:
<%# Page Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>
<asp:Content ID="errorTitle" ContentPlaceHolderID="TitleContent" runat="server">
Error
</asp:Content>
<asp:Content ID="errorContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>Shit happends</h2>
<p> <%: ViewData["messageError"]%></p>
<p>aaaaaaaaaaaaaaa!!!!!!!!!!!!!!!!!!!!</p>
</asp:Content>

Related

BeginForm Always calling Index when submitting

I'm using MVC BeginForm to submit form data to my ActionMethod in Controller. The problem is that when every I click on submit button it keeps calling Index method instead of Actual method defined in BeginForm.
Here is my View
#model HRMS.DBModel.department
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("save", "Department", FormMethod.Post))
{
#Html.TextAreaFor(model => model.Name, new { #class = "form-control" })
<input type="submit" value="submit" />
}
and here is the Department Controller
public class DepartmentController : Controller
{
// GET: Department
public ActionResult Index()
{
return View();
}
[HttpPost]
[AllowAnonymous]
public ActionResult save()
{
return View();
}
}
and RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Location", action = "Index", id = UrlParameter.Optional }
);
}
I searched on google even found solutions but still my problem is still there.
Any help will be appreciated.
Thanks
Issue Resolved there was a form tag inside my Master page due to which it was calling Index Method, I removed that form tag and now its working fine

ASP MVC Redirecting to error page

I'm trying to handle eventual errors in my view, by using the HandleError attribute on my view:
The reason why the Action is called 'Error' is because it gets a list of logged errors from a database.
[HandleError]
public ActionResult Error(int? page)
{
var errors = errorRepository.GetErrors();
// stuff for paging
var pageSize = 10;
var pageNumber = (page ?? 1); // if there is no page, return page 1
return View("Error", errors.ToPagedList(pageNumber, pageSize));
}
This is the error page in the /Shared/ folder:
#model System.Web.Mvc.HandleErrorInfo
#{
ViewBag.Title = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
But for some reason, the error page is never being shown, even though I've forced an exception in the action method. It just goes to the default url in my RouteConfig file.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Any hint as to why it doesn't show my error page is greatly appreciated!
I am sorry I have to add this as answer, but I don't have enough points to comment.
To be able to help you I need to see the code within the HandleErrorAttribute. However what you normally want to do in these cases is:
1) Add a config setting in the web.config to say that you will handle the exceptions on your own. Something like:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error">
<error statusCode="500" redirect="~/Error/InternalServer" />
<error statusCode="404" redirect="~/Error/NotFound" />
</customErrors>
</system.web>
2) Add the methods to accept those incoming calls in the ErrorController (In this case Index(), InternalServer(), NotFound())
3) Get the logs from your database and display them to the user than

ASP.NET MVC Search Results Page MapRoute Doesn't Work

How can i set mapRoute for search results page? My code doesn't work.
Global.asax.cs
routes.MapRoute(
name: "SearchResults",
url: "{action}/{Keyword}",
defaults: new { controller = "Home", action = "Search" }
);
Search Form
#using (Html.BeginForm("Search", "Home", FormMethod.Get))
{
#Html.TextBox("Keyword",null , new { #class = "SearchBox" })
<input type="submit" value="Search" />
}
HomeController.cs
public ActionResult Search(string Keyword)
{
GamesContext db = new GamesContext();
var SearchResults= (from i in db.Games where i.GameName.Contains(Keyword) || i.GameDesc.Contains(Keyword) select i).Take(20).ToList();
return View(SearchResults.AsEnumerable());
}
This one works for me (should be before default route):
routes.MapRoute(
"SearchResults",
"Search/{Keyword}",
new { controller = "Search", action = "SearchAction" }
);
Creating an ActionLink and MapRoute that there is a constant name in it
And there's a point to use new controller for search instead of home with this route.

TextBox Value gets blank on Submit

I created a application in MVC2 by choosing (ASP.Net MVC 2 Web Application). This provided some Home/About Controllers/Models/Views.
I additionally created a Model with the Name of Index like below...
namespace MvcApplication1.Models
{
public class Index
{
[DataType(DataType.Text)]
public String Name { get; set; }
}
}
Following is my Index View
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
{%>
<%:Html.TextBoxFor(x=> x.Name) %>
<input type="submit" name="Click here" />
<%} %>
</asp:Content>
Following is my Controller
[HttpPost]
public ActionResult Index(Index Model)
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
Question
When I keep the Index controller like below. and If I click the submit button. This is clearing the TextBox COntrols. Like below
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
TextBox will not be cleared in case in incorporating the Model as Parameter in the Action method...
What's the reason for this behaviour ?
MVC doesn't maintain state between postbacks like WebForms does.
Fields are repopulated from values in the ModelState which are only added there if they are seen by the modelbinder on postback (and potentially only if there is a validation error?). Honestly i would almost prefer if it didn't do it automatically. However if you postback an invalid value (eg a string to an integer field) you need an somewhere which can store the invalid value so it can be repopulated along with a validation error.
Other than that automatic method, you need to manually pass the model back to the view for it to be populated
[HttpPost]
public ActionResult Index(Index Model)
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View(Model);
}
Your controller should look like this for the user input to persit in the view after the submit button is clicked '
public ActionResult Index( )
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
var model = new Index();
return View( model );
}
[HttpPost]
public ActionResult Index(Index model )
{
return View(model);
}

Asp.net mvc route drops numeric folder at the end of a wildcard

So we have a route setup that has a wildcard at the end to capture a file path, the route might look like:
/{browserName}/{browserVersion}/{locale}/{*packageName}
The problem comes in when we try a path like:
/FF/3/en-US/scripts/packages/6/super.js
What ends up getting passed to the controller as packageName is:
/scripts/packages/super.js
Using the route tester program this also happens so we're at a total loss of why this is. If you replace the 6 with a string, it works, if you add another numeric folder before the 6 it does get included so it appears to just drop if the last folder is numeric. Anyone know why this is?
I created the default asp.net mvc2 project in VS2008 and changed the following code:
In the global.asax.cs I have this code:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"test", // Route name
"{browserName}/{browserVersion}/{locale}/{*packageName}",
new { controller = "Test", action = "Index", browserName = "IE", browserVersion = "8", locale = "en-US" , packageName = UrlParameter.Optional } // Parameter defaults
);
}
And next I added a TestController:
public class TestController : Controller
{
public ActionResult Index(
string browserName,
string browserVersion,
string locale,
string packageName)
{
return View();
}
}
And a empty Index View:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Index</h2>
</asp:Content>
for convenience I added a link in the site.master for the url you specified:
<li>Test</li>
Next I set a breakpoint in the Index action of the TestController.
When I hover over the packageName parameter I see "scripts/packages/6/super.js"
So I can't reproduce the behavior you got.
Are you using VS2008 and MVC2 or other versions?

Resources