@@ -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()); | |||
} | |||
} |
@@ -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 | |||
{ |
@@ -65,7 +65,7 @@ namespace Teknik | |||
} | |||
//routeData.Values["sub"] = subdomain; | |||
if (subDomain == subdomain) | |||
if (subDomain == "*" || subDomain == subdomain) | |||
{ | |||
return routeData; | |||
} |
@@ -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; |
@@ -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; |
@@ -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 } | |||
); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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 } | |||
); | |||
); | |||
} | |||
} | |||
} |
@@ -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; } | |||
} | |||
} |
@@ -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> |
@@ -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> | |||
@@ -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> |
@@ -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> | |||
@@ -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", |
@@ -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} |
@@ -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 | |||
{ |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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" /> |
@@ -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" /> |