十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
上篇博客,当没有权限的用户访问一些资源时,返回的是403错误,403对于用户来说是一个莫名其妙的数字,我们当然要处理成友好的提示。
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:主机域名、网页空间、营销软件、网站建设、平泉网站维护、网站推广。
关于错误处理,翻看了一下Nancy的源码,是这样处理的,见下面地址:
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ErrorHandling/DefaultStatusCodeHandler.cs
其实Nancy是允许我们采用相同的办法处理,现在把DefaultStatusCodeHandler.cs的源码复制下来,改成我们自己的CustomStatusCode.cs如下,关于详细说明,参考Nancy源码DefaultStatusCodeHandler.cs。
using Nancy; using Nancy.ErrorHandling; using Nancy.ViewEngines; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Nancy.Responses.Negotiation; using Nancy.Extensions; using Nancy.IO; namespace NancySelfHostWeb { public class CustomStatusCode: IStatusCodeHandler { private const string DisableErrorTracesTrueMessage = "Error details are currently disabled. Please setStaticConfiguration.DisableErrorTraces = false;
to enable."; private readonly IDictionaryerrorMessages; private readonly IDictionary errorPages; private readonly IResponseNegotiator responseNegotiator; private readonly HttpStatusCode[] supportedStatusCodes = { HttpStatusCode.Forbidden, HttpStatusCode.NotFound}; public CustomStatusCode(IResponseNegotiator responseNegotiator) { this.errorMessages = new Dictionary { { HttpStatusCode.Forbidden, "查看是否有授权!" }, { HttpStatusCode.NotFound, "找不到你要的资源!" } }; this.errorPages = new Dictionary { { HttpStatusCode.Forbidden, LoadResource("NancySelfHostWeb.403.html") }, { HttpStatusCode.NotFound, LoadResource("NancySelfHostWeb.404.html") } }; this.responseNegotiator = responseNegotiator; } public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) { return this.supportedStatusCodes.Any(s => s == statusCode); } public void Handle(HttpStatusCode statusCode, NancyContext context) { if (context.Response != null && context.Response.Contents != null && !ReferenceEquals(context.Response.Contents, Response.NoBody)) { return; } if (!this.errorMessages.ContainsKey(statusCode) || !this.errorPages.ContainsKey(statusCode)) { return; } Response existingResponse = null; if (context.Response != null) { existingResponse = context.Response; } context.NegotiationContext = new NegotiationContext(); var result = new DefaultStatusCodeHandlerResult(statusCode, this.errorMessages[statusCode], StaticConfiguration.DisableErrorTraces ? DisableErrorTracesTrueMessage : context.GetExceptionDetails()); try { context.Response = this.responseNegotiator.NegotiateResponse(result, context); context.Response.StatusCode = statusCode; if (existingResponse != null) { context.Response.ReasonPhrase = existingResponse.ReasonPhrase; } return; } catch (ViewNotFoundException) { } this.ModifyResponse(statusCode, context, result); } private void ModifyResponse(HttpStatusCode statusCode, NancyContext context, DefaultStatusCodeHandlerResult result) { if (context.Response == null) { context.Response = new Response { StatusCode = statusCode }; } var contents = this.errorPages[statusCode]; if (!string.IsNullOrEmpty(contents)) { contents = contents.Replace("[DETAILS]", result.Details); } context.Response.ContentType = "text/html"; context.Response.Contents = s => { using (var writer = new StreamWriter(new UnclosableStreamWrapper(s), Encoding.UTF8)) { writer.Write(contents); } }; } private static string LoadResource(string filename) { // 获取当前资源文件 var resourceStream = typeof(CustomStatusCode).Assembly.GetManifestResourceStream(string.Format("{0}", filename)); if (resourceStream == null) { return string.Empty; } using (var reader = new StreamReader(resourceStream)) { return reader.ReadToEnd(); } } internal class DefaultStatusCodeHandlerResult { public DefaultStatusCodeHandlerResult(HttpStatusCode statusCode, string message, string details) { this.StatusCode = statusCode; this.Message = message; this.Details = details; } public HttpStatusCode StatusCode { get; private set; } public string Message { get; private set; } public string Details { get; private set; } } } }
这样还可以把Nancy内置的500,404错误改成我们自定义的显示。
有时觉得这样太麻烦,可以自大在Module中去判断登录用户是否具有角色,代码如下
using Nancy; using Nancy.Security; using System.Linq; namespace TestSelfHostWeb.Modules { public class IndexModule : NancyModule { public IndexModule() { //开启全局验证 this.RequiresAuthentication(); Get["/"] = parameters => { //开启角色验证,只有该角色可以访问本路由 //this.RequiresClaims("admin"); //自己判断登录角色具有权限 if (!this.Context.CurrentUser.Claims.Contains("admin")) { return View["error"];//定义一个错误页面error.cshtml即可 } return View["index"]; }; } } }