how to handle this in mvc 3 and iis 6 like stackoverflow? - asp.net-mvc

how to handle 400 bad request like stackoverflow in mvc 3 , iis 6 ?
eg: www.stackoverflow.com/a<
return 404 not found page , instead of a YSOD page
updated: why this does not work ?
<httpErrors errorMode="Detailed">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" subStatusCode="-1" path="/notfound" responseMode="ExecuteURL" />
<error statusCode="400" subStatusCode="-1" path="/Error" responseMode="ExecuteURL" />
</httpErrors>

Use customErrors tag of web.config:
<customErrors mode="On" defaultRedirect="UrlToRedirect" >
<error statusCode="400" redirect="UrlToRedirect"/>
</customErrors>
Eg.:
<customErrors mode="On" defaultRedirect="~/Error/Index">
<error statusCode="400" redirect="~/Error/Index"/>
</customErrors>
if UrlToRedirect = "~/Error/Index", Here, in this url, "Error" is the name of controller & "Index" is the name of Action method which returns Error View Page.
public class ErrorController : Controller
{
public ActionResult Index()
{
return View("Error");
}
}
In the "\Views\Shared Folder" of you application, you have "Error.cshtml" view page.

Related

Custom Error pages in MVC ASP NET for all errors

i want in my app to have custom error pages for 401, 404 etc error codes.
I try this but doesn't work?
In Web.config
<customErrors mode="Off" /> //Under system.web
<httpErrors errorMode="Custom" existingResponse="Replace" >//Under system.webServer
<clear />
<remove statusCode="401"/>
<error statusCode="401" responseMode="ExecuteURL" path="/Error/Unauthorized" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error" />
</httpErrors>
I have create also Error controller and Unauthorized views.
How can this work?
Example:
web.config:
in system.web add
<customErrors mode="RemoteOnly" defaultRedirect="~/error">//RemoteOnly means that on local network you will see real errors
<error statusCode="401" path="~/Error/Unauthorized" />
<error statusCode="404" path="~/Error/NotFound" />
<error statusCode="500" path="~/Error" />
</customErrors>
in system.webServer add
<httpErrors errorMode="Detailed" />
Controller:
your controller something like
public class ErrorController : Controller
{
public ViewResult Index()
{
return View("Error");
}
public ViewResult NotFound()
{
Response.StatusCode = 404;
return View("NotFound");
}
}
View:
and your view something like
#model System.Web.Mvc.HandleErrorInfo
#{
Layout = "_Layout.cshtml";
ViewBag.Title = "Error";
}
<div class="list-header clearfix">
<span>Error</span>
</div>
<div class="list-sfs-holder">
<div class="alert alert-error">
An unexpected error has occurred. Please contact the system administrator.
</div>
#if (Model != null && HttpContext.Current.IsDebuggingEnabled)
{
<div>
<p>
<b>Exception:</b> #Model.Exception.Message<br />
<b>Controller:</b> #Model.ControllerName<br />
<b>Action:</b> #Model.ActionName
</p>
</div>
}
</div>
Hopefully it's help for you.

WebAPI + SimpleMembership + WebSecurity - can never authenticate?

I'm trying to implement a single-page app. I carried over some of my working code from another project (MVC4) to implement authentication. Right now I see cookies being set, but WebSecurity / User.Identity do not seem to be working for some reason. After logging in, subsequent requests never validate as authenticated, either via WebSecurity.IsAuthenticated, or User.Identity.IsAuthenticated. Does anyone know why this is happening?
Controller code:
public class AccountController : ApiController {
private readonly UserService _userService;
public AccountController() {}
public AccountController(UserService userService) {
_userService = userService;
}
[AllowAnonymous]
[HttpGet]
[Route("api/authpayload")]
// This gets called when the app loads. Always, User.Identity.IsAuthenticated is false.
public HttpResponseMessage AuthPayload() {
var payload = new AuthPayloadDto();
try {
var userId = WebSecurity.GetUserId(User.Identity.Name);
if (User.Identity.IsAuthenticated && userId > 0) {
payload.Username = User.Identity.Name;
} else {
LogOut();
payload.IsAuthenticated = false;
}
return Request.CreateResponse(HttpStatusCode.OK, payload);
} catch (Exception e) {
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
[HttpPost]
[Route("api/login")]
[AllowAnonymous]
public HttpResponseMessage LogIn(LoginModel model) {
if (!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
try {
if (WebSecurity.IsAuthenticated)
return Request.CreateResponse(HttpStatusCode.Conflict, "already logged in.");
if (!WebSecurity.UserExists(model.Username))
return Request.CreateResponse(HttpStatusCode.Conflict, "User does not exist.");
if (WebSecurity.Login(model.Username, model.Password, persistCookie: model.RememberMe)) {
// This code always gets hit when I log in, no problems. I see a new cookie get sent down as well, using Chrome debugger.
var payload = new AuthPayloadDto();
return Request.CreateResponse(HttpStatusCode.OK, payload);
}
LogOut();
return Request.CreateResponse(HttpStatusCode.Forbidden, "Login Failed.");
} catch (Exception e) {
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
Web.config:
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/" timeout="2880" />
</authentication>
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<!--
If you are deploying to a cloud environment that has multiple web server instances,
you should change session state mode from "InProc" to "Custom". In addition,
change the connection string named "DefaultConnection" to connect to an instance
of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express.
-->
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
</system.web>
The cookie that gets sent after login is not expired, and it does get sent back on subsequent requests, but IsAuthenticated is always false. What am I doing wrong?
Update:
I updated my web.config to the following to get everything working:
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear />
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
</system.web>
But I'd like to leave this open in case anyone has an explanation of why this works; I'm pretty lost.
In my current mvc 4 project with mssql,
its a simple one i so I just wanted very simple memmbership provider
I disabled
InitializeSimpleMembershipAttribute
by
[Authorize]
//[InitializeSimpleMembership]
public partial class AccountController : Controller
and added this code to global.asax under Application_Start
WebSecurity.InitializeDatabaseConnection(
connectionStringName: "DefaultConnection",
userTableName: "UserProfile",
userIdColumn: "UserID",
userNameColumn: "UserName",
autoCreateTables: true);
in my sql database the application created some tables on of them was Roles and UserInRoles just added the roles I needed like Admin, customer, etc...
and I restrict the access to some Controllers or Actions by adding this code
[Authorize(Roles = "Admin")]
public class MessagesController : Controller

Securing ELMAH in ADFS Claims aware MVC 4 app using elmah.mvc.allowedRoles AppSettings

ELMAH for MVC support following appsettings configurations
elmah.mvc.allowedRoles
elmah.mvc.allowedUsers
to secure the elmah route path using roles/users. Apparently, it works fine for windows or forms authentications. But I couldn't make it working for the claim based authentication.
Does anyone have experience with this?
I do this in web config
<elmah>
<security allowRemoteAccess="true" />
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="elmah-sqlserver" applicationName="Eers.Web"/>
</elmah>
and further down
<location path="elmah">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path="elmah.axd" inheritInChildApplications="false">
<system.web>
<httpHandlers>
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="ELMAH" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
</handlers>
</system.webServer>
</location>
If you take note of the node it works just like any other security in MVC. It does not work with Claims though. for that You will have to write an Action filter
<authorization>
<allow users="*"/>
</authorization>
Here is my Actionfilter
public class ElmahRequestAuthorizationFilter : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.IsChildAction) return;
var controller = filterContext.RouteData.Values["controller"] as string;
if (controller != null && controller.ToLowerInvariant() != "elmah") return;
var authenticationComponent = GetAuthenticationInfo() // A method that will return us roles;
var goodRoles = new List<string> {
"TestRole",
"ThirdLevelSupport",
"Administrator"
};
var roles = authenticationComponent.Roles ?? new List<string>();
var thouShaltPass = roles.Intersect(goodRoles).Any();
if (!thouShaltPass)
{
throw new HttpException(404, "Not Found");
}
}
}

Configuring Magical Unicorn Mvc Error Toolkit

I am trying to configure the Magical Unicorn Mvc Error Toolkit (v 2.1.2) on my MVC4 web site but I can't get it to work. Here's my code:
Web.config
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Error/ServerError">
<error statusCode="404" redirect="~/Views/Error/NotFound.cshtml" />
</customErrors>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="~/Error/NotFound" responseMode="ExecuteURL" />
<error statusCode="500" path="~/Error/ServerError" responseMode="ExecuteURL" />
</httpErrors>
<system.webServer>
Error Controller
public class ErrorController : Controller
{
public ActionResult NotFound()
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
}
public ActionResult ServerError()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return View();
}
}
[These were based on this https://stackoverflow.com/a/7499406/236860 post]
CustomerErrorHandler.cs (App_Start)
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using WorldDomination.Web.Mvc;
using CustomErrors.App_Start;
[assembly: WebActivator.PreApplicationStartMethod(typeof(CustomErrorHander), "PreStart")]
namespace CustomErrors.App_Start
{
public static class CustomErrorHander
{
public static void PreStart()
{
// Register the custom error handling module.
DynamicModuleUtility.RegisterModule(typeof (CustomErrorHandlingModule));
}
}
}
I am testing this application in Visual Studio 2012 using IIS Express. If I try to navigate to a non-existent page, or go to an action method that calls an exception I either get the default browser error page or a blank page.
I have also modified the above code as suggested at ASP.NET MVC Custom Error Pages with Magical Unicorn but this dis not seem to make any difference.
Can anyone point me in the right direction to get this working.
In the end, I could not get the Magical Unicorn Mvc Error Toolkit to work. The good news is that I don't think I had to! Since I am deploying the MVC application to an IIS 7.5 web server, I could use the later system.webServer.httpErrors section of my Web.config and a custom error controller.
Web.Config
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="false" targetFramework="4.5">
<customErrors mode="Off" /> <!-- IMPORTANT -->
...
</system.web>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/AccessDenied" />
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
<remove statusCode="500" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error/ApplicationError" />
</httpErrors>
...
</system.webServer>
Error Controller
public class ErrorController : Controller
{
public ActionResult AccessDenied()
{
Response.StatusCode = (int)HttpStatusCode.Forbidden;
Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
// return Json friendly response here
}
return View();
}
public ActionResult NotFound()
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
// return Json friendly response here
}
return View();
}
public ActionResult ApplicationError()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
Response.TrySkipIisCustomErrors = true;
if (Request.IsAjaxRequest())
{
// return Json friendly response here
}
return View();
}
}
This all seems to work well with IIS Express and IIS 7.5.
Elmah logs the errors without any changes to the default error filters.
Fiddler also suggests that the correct HTTP Status codes are also being correctly maintained.

Why am I getting duplicate exception entries using ELMAH in ASP.NET MVC?

I'm brand new to ELMAH but I've been working with MVC for a little while now. After reading several blogs on the subject I'm pursuing the road of having an ErrorController that handles 404 and unknown-error pages, and making a default route that forwards all unknown paths to the 404 action on that controller.
The problem is that ELMAH logs every error twice; the detail logs are completely identical except for their identification number specified in brackets in the title.
Has anyone else run into this? The routing seems to work great apart from having to ditch default {controller}/{action}/{id} route.
Here's my configuration:
<configSections>
...
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
...
</configSections>
<system.web>
...
<customErrors mode="On" defaultRedirect="~/error/unknown/">
<error statusCode="404" redirect="~/error/notfound/"/>
</customErrors>
...
<httpHandlers>
...
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>
...
</httpHandlers>
...
<httpModules>
...
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
</httpModules>
</system.web>
<system.webserver>
<modules runAllManagedModulesForAllRequests="true">
...
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
</modules>
<handlers>
...
<add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</handlers>
</system.webserver>
<elmah>
<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/errorlogpath" />
</elmah>
And routing code:
routes.MapRoute(
"ErrorDefault",
"error/{action}",
new { controller = "error", action = "unknown", id = "" }
);
routes.MapRoute(
"Default",
"{*url}",
new { controller = "error", action = "notfound", id = "" }
);
EDIT: Here's the ErrorController as well, just for my testing purposes:
/// <summary>
/// Handles error page routing
/// </summary>
public class ErrorController : Controller
{
/// <summary>
/// Action for unknown errors
/// </summary>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult Unknown()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return View();
}
/// <summary>
/// Action for 404s
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult NotFound(string path)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
}
}
Why do you have to ditch the default route?
I see that you're defining an ErrorDefault route and a catchAll route, which seems redundant to me. You'd want the catchAll route to handle any unknown route so you'd want to define the error in there.
You could try something like:
// All other pages use the default route.
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Applications", action = "Index", id = "" }
);
// Show a 404 error page for anything else.
routes.MapRoute("Error", "{*url}",
new { controller = "Error", action = "notfound" }
);
Could the redundant route be the cause of the double entries in the error log?

Resources