Browse Source

Added custom error handling

tags/2.0.3
Teknikode 4 years ago
parent
commit
8a2db1de87

+ 2
- 2
Teknik/App_Start/FilterConfig.cs View File

@@ -7,8 +7,8 @@ namespace Teknik
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new System.Web.Mvc.AuthorizeAttribute());
//filters.Add(new HandleErrorAttribute());
filters.Add(new AuthorizeAttribute());
filters.Add(new RequireHttpsAttribute());
}
}

+ 1
- 0
Teknik/App_Start/RouteConfig.cs View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Teknik.Areas.Error.Controllers;

namespace Teknik
{

+ 1
- 1
Teknik/App_Start/SubdomainRoute.cs View File

@@ -65,7 +65,7 @@ namespace Teknik
}

//routeData.Values["sub"] = subdomain;
if (subDomain == subdomain)
if (subDomain == "*" || subDomain == subdomain)
{
return routeData;
}

+ 3
- 2
Teknik/App_Start/SubdomainRouteExtension.cs View File

@@ -30,13 +30,14 @@ namespace Teknik
return route;
}

public static SubdomainRoute MapSubdomainRoute(this RouteCollection routes, string name, string subDomain, string url, object defaults, string[] namespaces)
public static SubdomainRoute MapSubdomainRoute(this RouteCollection routes, string name, string subDomain, string area, string url, object defaults, string[] namespaces)
{
SubdomainRoute route = new SubdomainRoute(
subDomain,
url,
new RouteValueDictionary(defaults),
new RouteValueDictionary(namespaces),
new RouteValueDictionary(new { }),
new RouteValueDictionary(new { Area = area, Namespaces = namespaces }),
new MvcRouteHandler());
routes.Add(name, route);
return route;

+ 0
- 2
Teknik/Areas/About/Controllers/AboutController.cs View File

@@ -11,8 +11,6 @@ namespace Teknik.Areas.About.Controllers
public class AboutController : DefaultController
{
//[AllowAnonymous]
[AllowAnonymous]
// GET: About/About
public ActionResult Index()
{
ViewBag.Title = "About - " + Config.Title;

+ 0
- 8
Teknik/Areas/Dev/DevAreaRegistration.cs View File

@@ -22,14 +22,6 @@ namespace Teknik.Areas.Dev
new { controller = "Dev", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.DevController).Namespace }
);
context.MapSubdomainRoute(
"Dev_default", // Route name
"dev",
"", // URL with parameters
"Home",
new { controller = "Home", action = "Index" }, // Parameter defaults
new[] { typeof(HomeController).Namespace }
);
}
}
}

+ 50
- 5
Teknik/Areas/Error/Controllers/ErrorController.cs View File

@@ -3,21 +3,66 @@ using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Teknik.Areas.Error.ViewModels;
using Teknik.Controllers;

namespace Teknik.Areas.Error.Controllers
{
public class ErrorController : DefaultController
{
// GET: Error/Error
public ActionResult Index()
[AllowAnonymous]
public ActionResult Exception(Exception exception)
{
return View();
ViewBag.Title = "Exception - " + Config.Title;

Response.StatusCode = 200;

ErrorViewModel model = new ErrorViewModel();
model.Exception = exception;

return View(model);
}

[AllowAnonymous]
public ActionResult General(Exception exception)
{
ViewBag.Title = "Http Exception - " + Config.Title;

Response.StatusCode = (exception as HttpException).GetHttpCode();

ErrorViewModel model = new ErrorViewModel();
model.Description = exception.Message;
model.Exception = exception;

return View(model);
}

public ActionResult Http404()
[AllowAnonymous]
public ActionResult Http404(Exception exception)
{
return View();
ViewBag.Title = "404 - " + Config.Title;
ViewBag.Message = "Uh Oh, can't find it!";

Response.StatusCode = 404;

ErrorViewModel model = new ErrorViewModel();
model.Exception = exception;

return View(model);
}

[AllowAnonymous]
public ActionResult Http500(Exception exception)
{
ViewBag.Title = "500 - " + Config.Title;
ViewBag.Message = "Something Borked";

Response.StatusCode = 500;

ErrorViewModel model = new ErrorViewModel();
model.Exception = exception;

return View(model);
}
}
}

+ 6
- 5
Teknik/Areas/Error/ErrorAreaRegistration.cs View File

@@ -14,12 +14,13 @@ namespace Teknik.Areas.Error

public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"404-PageNotFound",
"{*url}",
new { controller = "ErrorController", action = "Http404" }, // Parameter defaults
context.MapSubdomainRoute(
"Error_404", // Route name
"*",
"Error/404", // URL with parameters
new { controller = "Error", action = "Http404" }, // Parameter defaults
new[] { typeof(Controllers.ErrorController).Namespace }
);
);
}
}
}

+ 3
- 0
Teknik/Areas/Error/ViewModels/ErrorViewModel.cs View File

@@ -9,5 +9,8 @@ namespace Teknik.Areas.Error.ViewModels
{
public class ErrorViewModel : ViewModelBase
{
public string Title { get; set; }
public string Description { get; set; }
public Exception Exception { get; set; }
}
}

+ 39
- 0
Teknik/Areas/Error/Views/Error/Exception.cshtml View File

@@ -0,0 +1,39 @@
@model Teknik.Areas.Error.ViewModels.ErrorViewModel

<div class="container">
<div class="row">
<div class="col-md-12">
<div class="error-template text-center">
<h1>Unexpected Error</h1>
<div class="error-details">
An unexpected error has occurred. Please contact the system administrator.
<br />
@if (Model != null && HttpContext.Current.IsDebuggingEnabled)
{
<div class="text-left">
<p>
<b>Exception:</b> @Model.Exception.Message
<br />
<b>Source:</b> @Model.Exception.Source
</p>
<div style="overflow:scroll">
<pre>@Model.Exception.StackTrace</pre>
</div>
</div>
}
</div>
<br />
<div class="error-actions">
<a href="@Url.SubAction("www", "Index", "Home", new { area = "Home"})" class="btn btn-primary btn-lg">
<span class="glyphicon glyphicon-home"></span>
Take Me Home
</a>
<a href="@Url.SubAction("contact", "Index", "Contact", new { area = "Contact"})" class="btn btn-default btn-lg">
<span class="glyphicon glyphicon-envelope"></span>
Contact Support
</a>
</div>
</div>
</div>
</div>
</div>

+ 22
- 0
Teknik/Areas/Error/Views/Error/General.cshtml View File

@@ -0,0 +1,22 @@
@model Teknik.Areas.Error.ViewModels.ErrorViewModel

<div class="container">
<div class="row">
<div class="col-md-12">
<div class="error-template text-center">
<h1>Http Exception</h1>
<h2>Status Code: @((Model.Exception as HttpException).GetHttpCode())</h2>
<div class="error-details">
Sorry, an error has occured: @Model.Description
</div>
<div class="error-actions">
<a href="@Url.SubAction("www", "Index", "Home", new { area = "Home"})" class="btn btn-primary btn-lg">
<span class="glyphicon glyphicon-home"></span>
Take Me Home
</a><a href="@Url.SubAction("contact", "Index", "Contact", new { area = "Contact"})" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact Support </a>
</div>
</div>
</div>
</div>
</div>


+ 8
- 2
Teknik/Areas/Error/Views/Error/Http404.cshtml View File

@@ -9,10 +9,16 @@
<div class="error-details">
Sorry, an error has occured, Requested page not found!
</div>
<br />
<div class="error-actions">
<a href="@Url.SubAction("www", "Index", "Home", new { area = "Home"})" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span>
<a href="@Url.SubAction("www", "Index", "Home", new { area = "Home"})" class="btn btn-primary btn-lg">
<span class="glyphicon glyphicon-home"></span>
Take Me Home
</a><a href="@Url.SubAction("contact", "Index", "Contact", new { area = "Contact"})" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact Support </a>
</a>
<a href="@Url.SubAction("contact", "Index", "Contact", new { area = "Contact"})" class="btn btn-default btn-lg">
<span class="glyphicon glyphicon-envelope"></span>
Contact Support
</a>
</div>
</div>
</div>

+ 42
- 0
Teknik/Areas/Error/Views/Error/Http500.cshtml View File

@@ -0,0 +1,42 @@
@model Teknik.Areas.Error.ViewModels.ErrorViewModel

<div class="container">
<div class="row">
<div class="col-md-12">
<div class="error-template text-center">
<h1>Oops!</h1>
<h2>500 Server Error</h2>
<div class="error-details">
Sorry, a server error occured. Please contact an Administrator about this error.
<br />
@if (Model != null && HttpContext.Current.IsDebuggingEnabled)
{
<div class="text-left">
<p>
<b>Exception:</b> @Model.Exception.Message
<br />
<b>Source:</b> @Model.Exception.Source
</p>
<div style="overflow:scroll">
<pre>@Model.Exception.StackTrace</pre>
</div>
</div>
}
</div>
<br />
<div class="error-actions">
<a href="@Url.SubAction("www", "Index", "Home", new { area = "Home"})" class="btn btn-primary btn-lg">
<span class="glyphicon glyphicon-home"></span>
Take Me Home
</a>
<a href="@Url.SubAction("contact", "Index", "Contact", new { area = "Contact"})" class="btn btn-default btn-lg">
<span class="glyphicon glyphicon-envelope"></span>
Contact Support
</a>
</div>
</div>
</div>
</div>
</div>



+ 7
- 0
Teknik/Areas/Home/HomeAreaRegistration.cs View File

@@ -23,6 +23,13 @@ namespace Teknik.Areas.Home
new { controller = "Home", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.HomeController).Namespace }
);
context.MapSubdomainRoute(
"Home_dev_blank", // Route name
"dev",
"", // URL with parameters
new { controller = "Home", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.HomeController).Namespace }
);
context.MapSubdomainRoute(
"Home_subdomain", // Route name
"www",

+ 35
- 0
Teknik/Content/teknik.css View File

@@ -237,6 +237,41 @@ textarea{
background-color:#FFFFFF;
}

.navbar-xs { min-height:22px; border-radius:0}
.navbar-xs .navbar-brand{ padding: 2px 8px;font-size: 14px;line-height: 14px; }
.navbar-xs .navbar-nav > li > a { border-right:1px solid #ddd; padding-top: 2px; padding-bottom: 2px; line-height: 16px }

.hero-widget { text-align: center; padding-top: 20px; padding-bottom: 20px; }
.hero-widget .icon { display: block; font-size: 96px; line-height: 96px; margin-bottom: 10px; text-align: center; }
.hero-widget var { display: block; height: 64px; font-size: 64px; line-height: 64px; font-style: normal; }
.hero-widget label { font-size: 17px; }
.hero-widget .options { margin-top: 10px; }

.error-template {padding: 40px 15px;text-align: center;}
.error-actions {margin-top:15px;margin-bottom:15px;}
.error-actions .btn { margin-right:10px; }

.jumbotron-sm { padding-top: 24px;
padding-bottom: 24px; }
.jumbotron small {
color: #FFF;
}

.h1 small {
font-size: 24px;
}

.bs-callout-warning {
background-color: #FCF8F2;
border-color: #F0AD4E;
}

.bs-callout {
border-left: 3px solid #F0AD4E;
margin: 20px 0;
padding: 20px;
}

.glyphicon-lg{font-size:3em}
.blockquote-box{border-right:5px solid #E6E6E6;margin-bottom:25px}
.blockquote-box .square{width:100px;min-height:50px;margin-right:15px;text-align:center!important;background-color:#E6E6E6;padding:15px 0}

+ 9
- 0
Teknik/Controllers/DefaultController.cs View File

@@ -3,6 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Teknik.Areas.Error.Controllers;
using Teknik.Areas.Error.ViewModels;
using Teknik.Configuration;

namespace Teknik.Controllers
@@ -32,8 +35,14 @@ namespace Teknik.Controllers
{
ViewBag.Title = Config.Title;
ViewBag.Message = Config.Description;

if (Response != null)
{
Response.SuppressFormsAuthenticationRedirect = true;
}
}
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{

+ 141
- 0
Teknik/Global.asax.cs View File

@@ -11,6 +11,9 @@ using System.Web.Security;
using Teknik.Migrations;
using System.Data.Entity.Migrations;
using Teknik.Areas.Profile.Models;
using System.ComponentModel;
using Teknik.Areas.Error.Controllers;
using System.Web.Helpers;

namespace Teknik
{
@@ -26,6 +29,14 @@ namespace Teknik
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}

protected void Application_EndRequest(object sender, EventArgs e)
{
var context = new HttpContextWrapper(Context);
context.Response.SuppressFormsAuthenticationRedirect = true;
context.Response.TrySkipIisCustomErrors = true;
}

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
@@ -58,5 +69,135 @@ namespace Teknik
}
}
}

protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();

Response.Clear();

HttpException httpException = exception as HttpException;

RouteData routeData = new RouteData();
routeData.DataTokens.Add("namespaces", new[] { typeof(ErrorController).Namespace });
routeData.DataTokens.Add("area", "Error");
routeData.Values.Add("controller", "Error");
if (httpException == null)
{
routeData.Values.Add("action", "Exception");
}
else //It's an Http Exception, Let's handle it.
{
switch (httpException.GetHttpCode())
{
case 401:
// Unauthorized.
routeData.Values.Add("action", "Http401");
break;
case 403:
// Forbidden.
routeData.Values.Add("action", "Http403");
break;
case 404:
// Page not found.
routeData.Values.Add("action", "Http404");
break;
case 500:
// Server error.
routeData.Values.Add("action", "Http500");
break;

// Here you can handle Views to other error codes.
// I choose a General error template
default:
routeData.Values.Add("action", "General");
break;
}
}

// Pass exception details to the target error View.
routeData.Values.Add("exception", exception);

// Clear the error on server.
Server.ClearError();

// Avoid IIS7 getting in the middle
Response.TrySkipIisCustomErrors = true;

// If it is an Ajax request, we should respond with Json data, otherwise redirect
if (IsAjaxRequest())
{
string jsonResult = string.Empty;
if (httpException == null)
{
jsonResult = Json.Encode(new { error = new { type = "Exception", message = exception.Message } });
}
else
{
jsonResult = Json.Encode(new { error = new { type = "Http", statuscode = httpException.GetHttpCode(), message = exception.Message } });
}
Response.Write(jsonResult);
}
else
{
// Call target Controller and pass the routeData.
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData));
}
}

//This method checks if we have an AJAX request or not
private bool IsAjaxRequest()
{
//The easy way
bool isAjaxRequest = (Request["X-Requested-With"] == "XMLHttpRequest")
|| ((Request.Headers != null)
&& (Request.Headers["X-Requested-With"] == "XMLHttpRequest"));

//If we are not sure that we have an AJAX request or that we have to return JSON
//we fall back to Reflection
if (!isAjaxRequest)
{
try
{
//The controller and action
string controllerName = Request.RequestContext.
RouteData.Values["controller"].ToString();
string actionName = Request.RequestContext.
RouteData.Values["action"].ToString();

//We create a controller instance
DefaultControllerFactory controllerFactory = new DefaultControllerFactory();
Controller controller = controllerFactory.CreateController(
Request.RequestContext, controllerName) as Controller;

//We get the controller actions
ReflectedControllerDescriptor controllerDescriptor =
new ReflectedControllerDescriptor(controller.GetType());
ActionDescriptor[] controllerActions =
controllerDescriptor.GetCanonicalActions();

//We search for our action
foreach (ReflectedActionDescriptor actionDescriptor in controllerActions)
{
if (actionDescriptor.ActionName.ToUpper().Equals(actionName.ToUpper()))
{
//If the action returns JsonResult then we have an AJAX request
if (actionDescriptor.MethodInfo.ReturnType
.Equals(typeof(JsonResult)))
return true;
}
}
}
catch
{

}
}

return isAjaxRequest;
}
}
}

+ 3
- 0
Teknik/Teknik.csproj View File

@@ -272,6 +272,9 @@
<Content Include="Areas\Error\Views\web.config" />
<Content Include="Areas\Error\Views\Error\Http404.cshtml" />
<Content Include="Areas\Error\Views\_ViewStart.cshtml" />
<Content Include="Areas\Error\Views\Error\Exception.cshtml" />
<Content Include="Areas\Error\Views\Error\General.cshtml" />
<Content Include="Areas\Error\Views\Error\Http500.cshtml" />
<None Include="Properties\PublishProfiles\Teknik Dev.pubxml" />
<None Include="Scripts\jquery-2.1.4.intellisense.js" />
<Content Include="Scripts\bootbox\bootbox.min.js" />

+ 6
- 1
Teknik/Web.config View File

@@ -29,12 +29,17 @@
<system.web>
<customErrors mode="Off" />
<authentication mode="Forms">
<forms loginUrl="~/Profile/Login" timeout="2880" />
</authentication>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
<system.webServer>
<!--<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="500" />
<error statusCode="500" responseMode="ExecuteURL" path="/Error/500" />
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/404" />
</httpErrors>-->
<modules>
<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />

Loading…
Cancel
Save