ASP.NET MVC Tanıtıcı Hatası


110

[HandleError]Asp.net MVC Preview 5'te filtreye nasıl gidebilirim ?
CustomErrors'ı Web.config dosyamda ayarlıyorum

<customErrors mode="On" defaultRedirect="Error.aspx">
  <error statusCode="403" redirect="NoAccess.htm"/>
  <error statusCode="404" redirect="FileNotFound.htm"/>
</customErrors>

ve [HandleError] öğesini şu şekilde Denetleyici Sınıfımın üstüne koyun:

[HandleError]
public class DSWebsiteController: Controller
{
    [snip]
    public ActionResult CrashTest()
    {
        throw new Exception("Oh Noes!");
    }
}

Sonra denetleyicilerimin bu sınıftan miras almasına izin veriyorum ve CrashTest () 'i çağırıyorum. Görsel stüdyo hatada durur ve devam etmek için f5 tuşuna basıldıktan sonra Error.aspx? Aspxerrorpath = / sxi.mvc / CrashTest'e yeniden yönlendirilirim (burada sxi, kullanılan denetleyicinin adıdır. Elbette yol bulunamıyor ve alıyorum "'/' Uygulamasında Sunucu Hatası." 404.

Bu site önizleme 3'ten 5'e taşınmıştır. Hata işleme dışında her şey çalışır (bağlantı noktasına çok fazla çalışma yapılmadı). Tamamen yeni bir proje oluşturduğumda, hata işleme işe yarıyor gibi görünüyor.

Fikirler?

--Not--
Bu soru şu anda 3K'dan fazla görüntülendiğinden, şu anda kullandığım şeyi (ASP.NET MVC 1.0) koymanın yararlı olacağını düşündüm. Gelen mvc contrib projesi Muhtemelen de bunu kontrol etmelidir "RescueAttribute" denilen parlak bir nitelik vardır;)


Bağlantı RescueAttribute: Kaynağın mvccontrib.codeplex.com/SourceControl/changeset/view/...
Peter

Yanıtlar:


158
[HandleError]

Sınıfınıza (veya bu konudaki eylem yönteminize) yalnızca HandleError özniteliğini sağladığınızda, işlenmemiş bir istisna oluştuğunda, MVC önce Denetleyicinin Görünüm klasöründe "Hata" adlı karşılık gelen bir Görünümü arayacaktır. Orada bulamazsa, Paylaşılan Görünüm klasörüne bakmaya devam eder (varsayılan olarak içinde bir Error.aspx dosyası olması gerekir)

[HandleError(ExceptionType = typeof(SqlException), View = "DatabaseError")]
[HandleError(ExceptionType = typeof(NullReferenceException), View = "LameErrorHandling")]

Ayrıca, aradığınız istisna türü hakkında belirli bilgiler içeren ek öznitelikleri de biriktirebilirsiniz. Bu noktada, Hatayı varsayılan "Hata" görünümü dışında belirli bir görünüme yönlendirebilirsiniz.

Daha fazla bilgi için bir göz atın Scott Guthrie'nin bununla ilgili blog gönderisine .


1
Genişletilmiş bilgi için teşekkürler. Neyi yanlış yaptığımı bilmiyorum ama yeni bir proje yarattım, içindeki tüm mevcut görünümleri, kontrolörleri ve modelleri taşıdım ve şimdi çalışıyor. Yine de seçici görüşleri bilmiyordum.
Boris Callens

Bu istisnaların günlüğe kaydedilmesi isteniyorsa, bu görünüme kod arkası eklemek için kabul edilebilir bir yer midir?
Peter J

6
İkonik, işte benim yorumunuza "geç olmaktan iyidir" cevabım: Bunun yerine, HandleErrorAttribute'u alt sınıflara ayırabilir ve "OnException" yöntemini geçersiz kılabilirsiniz: Ardından, istediğiniz günlük kaydı veya özel eylemleri ekleyin. Daha sonra istisnayı tamamen işleyebilir (context.ExceptionHandled öğesini true olarak ayarlayabilir) veya bunun için temel sınıfın kendi OnException yöntemine geri dönebilirsiniz. İşte bu konuda yardımcı olabilecek mükemmel bir makale: blog.dantup.me.uk/2009/04/…
Funka

Ben bu içini işleyebilir böylece denetleyicilerin şey var global.asaxgibi bu kullanıcılara bir ileti gösterilmesi için?
shaijut

@PartialView ile aynı hata sayfasını kullanmaya ve istisna oluştuktan sonra bunu kalıcı iletişim kutusunda oluşturmaya ne dersiniz? Cevabınızda bir örnek verebilir misiniz? Başarmak istediğim şey, MVC'de PartialView kullanarak Global Hata işleme konusunda açıklandı .
Jack

23

Ayrıca, http hata kodunu 500'e ayarlamayan hataların da not edilmesi gerekir.

(örn. UnauthorizedAccessException)

HandleError filtresi tarafından ele alınmayacaktır.


1
Doğru, ancak MVC'deki RescueAttribute katkısına bakın (OP'deki bağlantı)
Boris Callens

14

500'e http hata kodu için çözüm bu, [ERROR] adlı bir özniteliktir ve onu bir eyleme geçirir

public class Error: System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
    {

            if (filterContext.HttpContext.IsCustomErrorEnabled)
            {
                filterContext.ExceptionHandled = true;

            }
            base.OnException(filterContext);
            //OVERRIDE THE 500 ERROR  
           filterContext.HttpContext.Response.StatusCode = 200;
    }

    private static void RaiseErrorSignal(Exception e)
    {
        var context = HttpContext.Current;
      // using.Elmah.ErrorSignal.FromContext(context).Raise(e, context);
    } 

}

//MİSAL:

[Error]
[HandleError]
[PopulateSiteMap(SiteMapName="Mifel1", ViewDataKey="Mifel1")]
public class ApplicationController : Controller
{
}

12

MVC'deki öznitelikler, get ve post yönteminde hata işlemede çok kullanışlıdır , ayrıca ajax çağrısını da izler .

Uygulamanızda bir temel denetleyici oluşturun ve bunu ana denetleyicinizde (EmployeeController) devralın.

public class EmployeeController: BaseController

Temel denetleyicide aşağıdaki kodu ekleyin.

/// <summary>
/// Base Controller
/// </summary>
public class BaseController : Controller
{       
    protected override void OnException(ExceptionContext filterContext)
    {
        Exception ex = filterContext.Exception;

        //Save error log in file
        if (ConfigurationManager.AppSettings["SaveErrorLog"].ToString().Trim().ToUpper() == "TRUE")
        {
            SaveErrorLog(ex, filterContext);
        }

        // if the request is AJAX return JSON else view.
        if (IsAjax(filterContext))
        {
            //Because its a exception raised after ajax invocation
            //Lets return Json
            filterContext.Result = new JsonResult()
            {
                Data = Convert.ToString(filterContext.Exception),
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();

            filterContext.Result = new ViewResult()
            {
                //Error page to load
                ViewName = "Error",
                ViewData = new ViewDataDictionary()
            };

            base.OnException(filterContext);
        }
    }

    /// <summary>
    /// Determines whether the specified filter context is ajax.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    private bool IsAjax(ExceptionContext filterContext)
    {
        return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
    }

    /// <summary>
    /// Saves the error log.
    /// </summary>
    /// <param name="ex">The ex.</param>
    /// <param name="filterContext">The filter context.</param>
    void SaveErrorLog(Exception ex, ExceptionContext filterContext)
    {
        string logMessage = ex.ToString();

        string logDirectory = Server.MapPath(Url.Content("~/ErrorLog/"));

        DateTime currentDateTime = DateTime.Now;
        string currentDateTimeString = currentDateTime.ToString();
        CheckCreateLogDirectory(logDirectory);
        string logLine = BuildLogLine(currentDateTime, logMessage, filterContext);
        logDirectory = (logDirectory + "\\Log_" + LogFileName(DateTime.Now) + ".txt");

        StreamWriter streamWriter = null;
        try
        {
            streamWriter = new StreamWriter(logDirectory, true);
            streamWriter.WriteLine(logLine);
        }
        catch
        {
        }
        finally
        {
            if (streamWriter != null)
            {
                streamWriter.Close();
            }
        }
    }

    /// <summary>
    /// Checks the create log directory.
    /// </summary>
    /// <param name="logPath">The log path.</param>
    bool CheckCreateLogDirectory(string logPath)
    {
        bool loggingDirectoryExists = false;
        DirectoryInfo directoryInfo = new DirectoryInfo(logPath);
        if (directoryInfo.Exists)
        {
            loggingDirectoryExists = true;
        }
        else
        {
            try
            {
                Directory.CreateDirectory(logPath);
                loggingDirectoryExists = true;
            }
            catch
            {
            }
        }

        return loggingDirectoryExists;
    }

    /// <summary>
    /// Builds the log line.
    /// </summary>
    /// <param name="currentDateTime">The current date time.</param>
    /// <param name="logMessage">The log message.</param>
    /// <param name="filterContext">The filter context.</param>       
    string BuildLogLine(DateTime currentDateTime, string logMessage, ExceptionContext filterContext)
    {
        string controllerName = filterContext.RouteData.Values["Controller"].ToString();
        string actionName = filterContext.RouteData.Values["Action"].ToString();

        RouteValueDictionary paramList = ((System.Web.Routing.Route)(filterContext.RouteData.Route)).Defaults;
        if (paramList != null)
        {
            paramList.Remove("Controller");
            paramList.Remove("Action");
        }

        StringBuilder loglineStringBuilder = new StringBuilder();

        loglineStringBuilder.Append("Log Time : ");
        loglineStringBuilder.Append(LogFileEntryDateTime(currentDateTime));
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("Username : ");
        loglineStringBuilder.Append(Session["LogedInUserName"]);
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("ControllerName : ");
        loglineStringBuilder.Append(controllerName);
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("ActionName : ");
        loglineStringBuilder.Append(actionName);
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("----------------------------------------------------------------------------------------------------------");
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append(logMessage);
        loglineStringBuilder.Append(System.Environment.NewLine);
        loglineStringBuilder.Append("==========================================================================================================");

        return loglineStringBuilder.ToString();
    }

    /// <summary>
    /// Logs the file entry date time.
    /// </summary>
    /// <param name="currentDateTime">The current date time.</param>
    string LogFileEntryDateTime(DateTime currentDateTime)
    {
        return currentDateTime.ToString("dd-MMM-yyyy HH:mm:ss");
    }

    /// <summary>
    /// Logs the name of the file.
    /// </summary>
    /// <param name="currentDateTime">The current date time.</param>
    string LogFileName(DateTime currentDateTime)
    {
        return currentDateTime.ToString("dd_MMM_yyyy");
    }

}

================================================

Dizini Bulur: Root / App_Start / FilterConfig.cs

Aşağıdaki kodu ekleyin:

/// <summary>
/// Filter Config
/// </summary>
public class FilterConfig
{
    /// <summary>
    /// Registers the global filters.
    /// </summary>
    /// <param name="filters">The filters.</param>
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

AJAX Hatasını İzle:

Düzen sayfası yüklemesinde CheckAJAXError işlevini çağırın.

function CheckAJAXError() {
    $(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {

        var ex;
        if (String(thrownError).toUpperCase() == "LOGIN") {
            var url = '@Url.Action("Login", "Login")';
            window.location = url;
        }
        else if (String(jqXHR.responseText).toUpperCase().indexOf("THE DELETE STATEMENT CONFLICTED WITH THE REFERENCE CONSTRAINT") >= 0) {

            toastr.error('ReferanceExistMessage');
        }
        else if (String(thrownError).toUpperCase() == "INTERNAL SERVER ERROR") {
            ex = ajaxSettings.url;
            //var url = '@Url.Action("ErrorLog", "Home")?exurl=' + ex;
            var url = '@Url.Action("ErrorLog", "Home")';
            window.location = url;
        }
    });
};

AJAX isteklerinde istisna ayrıntılarını sızdırıyorsunuz, bunu her zaman istemezsiniz. Günlük kodunuz iş parçacığı için güvenli değil. Bir Hata görünümü olduğunu varsayıyorsunuz ve yanıt kodunu değiştirmeden bunu geri veriyorsunuz. Ardından JavaScript'teki belirli hata dizelerini kontrol edin (yerelleştirme ne olacak?). Temel olarak, mevcut bir yanıtın söylediği şeyi tekrarlıyorsunuz: " OnExceptionİstisnaları ele almak için geçersiz kıl " , ancak bunun oldukça kötü bir şekilde uygulandığını gösteriyor.
CodeCaster

@ School.Resource.Messages.ReferanceExist parametresi nedir?
Jack

@CodeCaster ASP.NET MVC'de AJAX ile böyle bir hata işleme yöntemini kullanmanın daha iyi bir yolunu biliyor musunuz? Herhangi bir yardım lütfen?
Jack

HTTP'nin amaçlandığı şekilde bir 400 veya 500 döndür. Yanıt gövdesinde belirli dizeler için araştırma yapmayın.
CodeCaster

@CodeCaster Bu sorunla ilgili olarak MVC'de PartialView kullanarak Global Hata işlemeye bir göz atabilir misiniz ?
Jack

4

Error.aspx eksik :) Önizleme 5'te, bu Görünümler / Paylaşılan klasörünüzde bulunur. Yeni bir Preview 5 projesinden kopyalamanız yeterlidir.


Cevabınız için teşekkürler, ancak Error.aspx sayfasını zaten kopyaladım. Normalde unutacağım bir şey olabilirdi, ama bu sefer değil. : P
Boris Callens

-1
    [HandleError]
    public class ErrorController : Controller
    {        
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult NotAuthorized()
        {
            //401
            Response.StatusCode = (int)HttpStatusCode.Unauthorized;

        return View();
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult Forbidden()
    {
        //403
        Response.StatusCode = (int)HttpStatusCode.Forbidden;

        return View();
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult NotFound()
    {
        //404
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    public ViewResult ServerError()
    {
        //500
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.