سؤال

نحن نستخدم ممتاز محمة للتعامل مع استثناءات غير معلقة في تطبيق Web ASP.NET 3.5. يعمل هذا بشكل جيد للغاية لجميع الموقع بصرف النظر عن خدمات WCF التي يتم استهلاكها باستخدام ميزات الراحة. عند حدوث استثناء ضمن أساليب التشغيل التي لا يتم التعامل معها بواسطة رمز التطبيق، يعالج WCF بطرق مختلفة اعتمادا على عقود الخدمة وإعدادات التكوين. هذا يعني أن الاستثناء لا ينتهي بإطلاق النار على ASP.NET httpapplication.Error الحدث الذي محمة الاستخدامات. الحلولان الذي أدركه للتعامل مع هذا هو:

  • التفاف جميع الأسلوب مكالمات في محاولة {} الصيد (استثناء السابق) {elmah.errorsignal.fromcurrentcontext (). رفع (السابقين)؛ يرمي؛ } للاتصال صراحة المحة داخل كتلة الصيد.
  • يستخدم iErrorhandler. كما هو موضح في هل سوف هيوز مشاركة مدونة جعل WCF ومحه يلعب لطيفا معا لعدد الدعوة إلى المحة إلى خطأ منفصل.

الخيار الأول بسيط للغاية ولكنه ليس بالضبط جاف. وبعد يتطلب منك الخيار الثاني فقط تزيين كل خدمة بسمة مخصصة بعد تنفيذ السمة والخلف. لقد فعلت هذا بناء على سوف العمل ولكن أريد التحقق من أن هذا هو النهج الصحيح قبل نشر الرمز.

هل هناك طريقة أفضل التي فاتنيها؟

Documenation MSDN ل iErrorhandler. يقول أن المقاود الطريقة هي المكان المناسب للقيام بالتسجيل ولكن محمة يصل إلى httpcontext.current.ApplicationInstance., ، وهو فارغ ضمن هذه الطريقة على الرغم من أن HttpContext.current متاح. إن إجراء المكالمة إلى elmah ضمن طريقة المتوفر هو عبارة عن حل عبء كما يتم تعيين التطبيق، لكن هذا لا يتطابق مع النوايا الموضحة في وثائق API. نسيت شيئا ما هنا؟ تفعل الوثائق الدولة التي يجب ألا تعتمد عليها في طريقة المقاظ التي يتم استدعاؤها في مؤشر ترابط التشغيل الذي قد يكون السبب في أن التطبيقات لاغية في هذا النطاق.

هل كانت مفيدة؟

المحلول

كان الحل من منشور مدونتي (المشار إليه في البروتوكول الاختياري) استنادا إلى حل موجود كنا نتمكن / نستخدم لتغيير رموز استجابة HTTP أثناء حالة الخطأ.

لذلك، بالنسبة لنا هو تغيير خط واحد لتمرير الاستثناء إلى المحة. إذا كان هناك حلا أفضل، أحب أن أعرف عن ذلك أيضا.

بالنسبة للأجيال / المرجع، والتحسين المحتمل - إليك الشفرة من الحل الحالي.

httperrorhandler و Serviceerrorbehaviourattribute فصول

using System;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using Elmah;
namespace YourApplication
{
    /// <summary>
    /// Your handler to actually tell ELMAH about the problem.
    /// </summary>
    public class HttpErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return false;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error != null ) // Notify ELMAH of the exception.
            {
                if (System.Web.HttpContext.Current == null)
                    return;
                Elmah.ErrorSignal.FromCurrentContext().Raise(error);
            }
        }
    }
    /// <summary>
    /// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
    /// ...and errors reported to ELMAH
    /// </summary>
    public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
    {
        Type errorHandlerType;

        public ServiceErrorBehaviourAttribute(Type errorHandlerType)
        {
            this.errorHandlerType = errorHandlerType;
        }

        public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
        }

        public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler;
            errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
            foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                channelDispatcher.ErrorHandlers.Add(errorHandler);
            }
        }
    }
}

مثال الاستخدام

تزيين خدمات WCF الخاصة بك مع سمة Serviceerrorbehaviour:

[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
  // ...
}

نصائح أخرى

عند إنشاء سلوكالسلمنت، من الممكن تنشيط السلوك باستخدام التكوين:

public class ErrorBehaviorExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(ServiceErrorBehaviourAttribute); }
    }

    protected override object CreateBehavior()
    {
        return new ServiceErrorBehaviourAttribute(typeof(HttpErrorHandler));
    }
}

التكوين:

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="elmah" type="Namespace.ErrorBehaviorExtensionElement, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <elmah />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

وبهذه الطريقة من الممكن أيضا استخدام الميمية بالاشتراك مع خدمات رياض!

لقد قمت بذلك على أساس عمل الإرادة ولكن أريد التحقق من أن هذا هو النهج الصحيح قبل نشر التعليمات البرمجية.

أعتقد أن هذا نهج كبير (كودوس لإرادة هذا النشر!). لا أعتقد أن الإرادة أو فقد فاتتك أي شيء هنا. تطبيق IERRORHANDER هو الطريقة المفضلة لفصل جميع الاستثناءات التي يمكن أن تتسبب في جميع الاستثناءات من جانب الخادم الممكنة والتي قد تتسبب في عدم وجود قناة الاتصالات (ممزقة)، وبالتالي فهي مكان طبيعي لربطه في بعض التسجيل مثل الممن.

مارك

قد يكون هذا واضحا بالنسبة لبعض الناس، لكنني أمضيت بعض الوقت أحاول معرفة سبب وجود httpccontext.current خالية رغم اتباع إجابة هيوز الممتازة. بحق، أدركت أن هذا كان بسبب تنشيط خدمة WCF الخاصة بي بواسطة رسالة MSMQ.

انتهى بي الأمر إعادة كتابة ProvideFault() طريقة:

if (HttpContext.Current == null)
{
    ErrorLog.GetDefault(null).Log(new Error(error));
}
else
{
    ErrorSignal.FromCurrentContext().Raise(error);
}

لم أتمكن من الحصول على الإجابة المقترحة مع خدمة بيانات WCF. أنا سيلت سمة السلوك، إلخ، ولكن لا يزال لم أحصل على أي أخطاء مسجلة. بدلا من ذلك، انتهى بي الأمر بإضافة ما يلي إلى تنفيذ الخدمة:

protected override void HandleException(HandleExceptionArgs args)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(args.Exception);
    base.HandleException(args);
}

لم أحاول القيام بذلك صراحة مع الأشياء البقية، ولم تستخدم إيماه نفسي، ولكن خيار آخر يستحق النظر إليه قد يكون هو ربط في WCF باستخدام WCF باستخدام WCF باستخدام idispatchmessageInspector. بدلا من reerrorhandler.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top