I have an ASP.Net MVC 2 web application where I have HomeController. Index method generates unauthorized exception. I have customErrors=on. Now I want to show a view Error.aspx in shared folder with Exception.Message. But I get Resource not found /Error in browser.
Note: I had gone through all the related links on StackOverflow.
any help?
Step by step:
Create a new ASP.NET MVC project using the default visual Studio wizard
Modify the HomeController so that it looks like this:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
throw new Exception("oops");
}
}
Add the following to the <system.web> section of web.config:
<customErrors mode="On" />
Run the application
As expected the ~/Views/Shared/Error.aspx is shown
Related
I am recently taking over a .NET MVC5 application.
In the HomeController.cs under the ActionResult method there is the following code;
throw new Exception("Test error page");
the above line of code trigger an error page under the view director error.cshtml
My question is how the above line of code trigger the error page I looked everywhere and there is nothing that connect that line of code in the controller to the error page. Would someone tell how it works?.
I usually use the following steps to create a custom error page:
Edit the web.config with <customError> tag.
Add [handleError] attribute in the Controller.
Add an error.cshmtl page in the shared directory under view.
What triggered this Error.cshtml, is the global HandleErrorAttribute that is added by default in the App_Start\FilterConfig.cs file when creating a new MVC project.
The default contents of this file is:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
Removing this HandleErrorAttribute addition will remove the search for Error.cshtml
My Question Is This
What configuration step have I missed to make Mvc Surface Controllers work in Umbraco?
My theory is that since there is a folder in the default Umbraco install called /umbraco/ which is used to connect to the CMS that the physical path is interfiering with the route /umbraco/surface/{Controller}/{Action} thus resulting in the ASP.NET YSOD (and an IIS 404
when I try to access a controller on that route that isn't defined.)
Background Information
I have added this class to my App_Code folder in a freshly downloaded copy of Umbraco 6.1.6:
public class MembersController : SurfaceController
{
public ActionResult Index()
{
return Content("Hello, Member!");
}
}
When I navigate to what I think should be the route for my Index() method, I get a YSOD that says the resource could not be found:
the code is not executed and the above error is displayed; however, if I change the Uri to garbage I get an IIS 404 error:
I started getting this in an existing site, thinking my site was screwed up I tried it in a new copy of Umbraco 6.1.6 and got the exact same results.
For the record, I have also tried MembersSurfaceController and its associated Uri, which has the exact same result as above. YSOD when I hit the valid route, and IIS 404 when I don't.
I have changed my umbracoSettings.config to MVC in the /config/ directory as well.
update
I'm using the out-of-the-box web.config file, which has this:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="UrlRewriteModule" />
<add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter" />
.
..
...
On my default Umbraco site I don't have any rewrite rules defined; but on my actual site I have several rewrite rules in place. I'm thinking that's not causing it since I'm seeing the same behavior on both sites though...
I have tried removing UrlRewrite completely I get the same results.
The following approach works for me in Umbraco 7.1, and I expect it to work in 6.1 as well:
Create folder called 'Controllers' within your App_Code folder, and put your surface controllers in there (so that they will be within the 'Controllers' namespace).
E.g. I have the following controller in the App_Code\Controllers folder (and hence, within the 'Controllers' namespace):
namespace Controllers
{
public class ServiceCentersController : SurfaceController
{
public ActionResult GetServiceCenters(string country = "", string region = "", string city = "")
{
...
}
}
}
My site runs on localhost, so I can invoke the GetServiceCenters action by navigating to:
http://localhost/umbraco/Surface/ServiceCenters/GetServiceCenters?country=aa®ion=bb&city=cc
You need a namespace for your controller - the code posted above doesn't have any namespace:
public class MembersController : SurfaceController
{
public ActionResult Index()
{
return Content("Hello, Member!");
}
}
That is why making a namespace of Controllers works ... but you could make this any logically named namespace you want.
I'm trying to understand HandleErrorAttribute in MVC3. (I also followed old article from ScottGu) I added the <customErrors mode="On" /> to the web.config file. All errors redirect to the \Views\Shared\Error.cshtml view. If I keep the HandleErrorAttribute or remove from the controller, there is no difference in the behavior.
Code of the controller
public class HomeController : Controller
{
[HandleError]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
throw new Exception();
return View();
}
}
Also, I show in some articles and SO post, that with <error redirect="..."/>, request can be redirected to the required view.
Qestions
What is the use of HandleErrorAttribute?
What is the advantage of using it over <customErrors.. ?
What can we achieve that is not achievable by <customErrors.. ?
1) The HandleErrorAttribute (MSDN) is a FilterAttribute that is used to handle controller actions that throw an error. I would suggest reading the documentation on the MSDN page as it describes exactly what it does and the constructors that it can take. Additionally in your webconfig you must have the customErrors section set to.
<system.web>
<customErrors mode="On" defaultRedirect="Error" />
</system.web>
2) Now the custom errors section is used to allow the Asp.Net application to control the behavior of the page when an error (Exception) is raised. (MSDN) When the custom Errors is set to On or RemoteOnly when an application exception happens the application will use the rules defined in the Web.config to either display the error message or redirect to a page.
3) Using the HandleErrorAttribute you can provide different redirections \ views based on the exception types raised.
I would recommend you view this SO topic for more information (read Elijah Manor's post). ASP.NET MVC HandleError
Cheers.
Background:
On a public facing ASP.NET MVC4 application, sometimes I receive inbound requests to a bad URL. The referrer is from outside so my app which is out of my control (I'm not generating the bad URL in my app). So MVC correctly raises an exception AND the user sees the custom error page. The global.asax is coded to email errors to me.
Problem. Although the URL is bad, the error I'm receiving is unexpected.
Ex:
- User navigates (from an external URL) to /Blog/View
- The Blog controller does not have a View action
- The user is presented with the Error500 custom error web page
- The error I receive by email is:
The view 'Error' or its master was not found or no view engine
supports the searched locations. The following locations were
searched: ~/Views/Blog/Error.aspx ~/Views/Blog/Error.ascx
~/Views/Shared/Error.aspx ~/Views/Shared/Error.ascx
~/Views/Blog/Error.cshtml ~/Views/Blog/Error.vbhtml
~/Views/Shared/Error.cshtml ~/Views/Shared/Error.vbhtml
I don't understand why ASP.NET MVC4 is looking for a view named "Error", and why MVC does not search for the view as specified (Error500) in the web.config. Here are the applicable source files:
The Web.Config:
<customErrors mode="RemoteOnly" defaultRedirect="~/Error/Error500">
<error statusCode="404" redirect="~/Error/Error404" />
</customErrors>
The ErrorController file:
public class ErrorController : Controller
{
public ActionResult Error500()
{
return View();
}
public ActionResult Error404()
{
return View();
}
}
The Error404.cshtml file (located in the /Views/Error folder):
#{
ViewBag.Title = "Oops...";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>That's interesting</h1>
<p>The page you were looking for could not be found.</p>
The Error500.cshtml file (located in the /Views/Error folder):
#{
ViewBag.Title = "Oops...";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>We're sorry about that</h1>
<p>Something unexpected just happened. Our IT staff has been notified...time to code a hot-fix!</p>
Are you sure that the user is hitting a URL that does not exist? It seems from a small repro that I just made that this works as desired if the action method does not exist. When an error is thrown inside an action method that was resolved by the routing and you are using the HandleErrorAttribute then you will get the error that you mention. What does your routing look like?
As an aside emailing your self on error is not a sustainable route to receiving errors about your application! You should look into an error logging service to handle this for you. I recommend Bugsnag. (Disclaimer: I work at Bugsnag :))
I have set up custom error pages on my site using
<customErrors mode="RemoteOnly" defaultRedirect="~/Error">
<error statusCode="500" redirect="~/Error/InternalError"/>
<error statusCode="404" redirect="~/Error/FileNotFound"/>
<error statusCode="403" redirect="~/Error/AccessDenied"/>
</customErrors>
however there is another area on the site, Suppliers, and when an error occurs in the supplier area the redirect goes to Suppliers/Error/_. Since I don't have any error pages here, the site just seems to hang never shows the error pages. How can I fix this without having to copy the error pages to the supplier area?
As far as I understand with MVC your URL make up, by default is:
Domain/Controller/Action/id
If you have an "Error" Controller. In your logic, you test to see if the request originated from an user of the site that would need to redirect to the "Suppliers" Error page
[HandleError]
public ActionResult Index()
{
// Test to see if you need to go to the SuppliersController
if (this.User.IsInRole("supplier"))
{
return Redirect("/Suppliers/Error");
}
else
{
return View(); // This returns the "Error" View from the shared folder
}
}
redirect to an Error handling action on your Suppliers Controller that will return the right view.
public class SuppliersController : Controller
{
//
// GET: /Suppliers/
public ActionResult Error()
{
return View("Error","SomeMasterPage"); // No "Error" view in Suppliers View folder, so it uses the one in shared folder
}
}
You can also use the [Authorize] attribute on your Suppliers Error Action to make sure the user is logged on.
In this way, you will get your desired /Suppliers/Error URL and can use the SuppliersController Action to specify the desired view, model, and master/Layout page.
also look at this very comprehensive reply to a similar question:
Best 404 example I can find for mvc
I guess removing the "~" before the error page should do the trick, you will need the "\" though.
Another way would be to write the FULL URL in the redirect/defaultRedirect attribute.