Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

}

Section 76.8: Throwing an exception

Your code can, and often should, throw an exception when something unusual has happened.

public void WalkInto(Destination destination)

{

if (destination.Name == "Mordor")

{

throw new InvalidOperationException("One does not simply walk into Mordor.");

}

// ... Implement your normal walking code here.

}

Section 76.9: Unhandled and Thread Exception

AppDomain.UnhandledException This event provides notification of uncaught exceptions.It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application.If su cient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery.Caution is advised, because program data can become corrupted when exceptions are not handled.

///<summary>

///The main entry point for the application.

///</summary>

[STAThread]

private static void Main(string[] args)

{

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);

}

Application.ThreadException This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads. Attach your event handlers to the ThreadException event to deal with these exceptions, which will leave your application in an unknown state. Where possible, exceptions should be handled by a structured exception handling block.

///<summary>

///The main entry point for the application.

///</summary>

[STAThread]

private static void Main(string[] args)

{

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);

Application.ThreadException += new ThreadExceptionEventHandler(ThreadException);

}

And finally exception handling

static void UnhandledException(object sender, UnhandledExceptionEventArgs e)

{

Exception ex = (Exception)e.ExceptionObject;

// your code

}

GoalKicker.com – C# Notes for Professionals

457

static void ThreadException(object sender, ThreadExceptionEventArgs e)

{

Exception ex = e.Exception;

// your code

}

Section 76.10: Implementing IErrorHandler for WCF Services

Implementing IErrorHandler for WCF services is a great way to centralize error handling and logging. The implementation shown here should catch any unhandled exception that is thrown as a result of a call to one of your WCF services. Also shown in this example is how to return a custom object, and how to return JSON rather than the default XML.

Implement IErrorHandler:

using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Runtime.Serialization.Json; using System.ServiceModel;

using System.ServiceModel.Web;

namespace BehaviorsAndInspectors

{

public class ErrorHandler : IErrorHandler

{

public bool HandleError(Exception ex)

{

// Log exceptions here

return true;

} // end

public void ProvideFault(Exception ex, MessageVersion version, ref Message fault)

{

//Get the outgoing response portion of the current context var response = WebOperationContext.Current.OutgoingResponse;

//Set the default http status code

response.StatusCode = HttpStatusCode.InternalServerError;

// Add ContentType header that specifies we are using JSON

response.ContentType = new MediaTypeHeaderValue("application/json").ToString();

// Create the fault message that is returned (note the ref parameter) with BaseDataResponseContract

fault = Message.CreateMessage( version,

string.Empty,

new CustomReturnType { ErrorMessage = "An unhandled exception occurred!" },

new DataContractJsonSerializer(typeof(BaseDataResponseContract), new List<Type> { typeof(BaseDataResponseContract) }));

if (ex.GetType() == typeof(VariousExceptionTypes))

{

// You might want to catch different types of exceptions here and process them

differently

}

GoalKicker.com – C# Notes for Professionals

458

// Tell WCF to use JSON encoding rather than default XML var webBodyFormatMessageProperty = new

WebBodyFormatMessageProperty(WebContentFormat.Json); fault.Properties.Add(WebBodyFormatMessageProperty.Name, webBodyFormatMessageProperty);

}// end

}// end class

}// end namespace

In this example we attach the handler to the service behavior. You could also attach this to IEndpointBehavior, IContractBehavior, or IOperationBehavior in a similar way.

Attach to Service Behaviors:

using System;

using System.Collections.ObjectModel; using System.ServiceModel;

using System.ServiceModel.Channels; using System.ServiceModel.Configuration; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher;

namespace BehaviorsAndInspectors

{

public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior

{

public override Type BehaviorType

{

get { return GetType(); }

}

protected override object CreateBehavior()

{

return this;

}

private IErrorHandler GetInstance()

{

return new ErrorHandler();

}

void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } // end

void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

{

var errorHandlerInstance = GetInstance();

foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)

{

dispatcher.ErrorHandlers.Add(errorHandlerInstance);

}

}

void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } // end

GoalKicker.com – C# Notes for Professionals

459

}// end class

}// end namespace

Configs in Web.config:

...

<system.serviceModel>

<services>

<service name="WebServices.MyService">

<endpoint binding="webHttpBinding" contract="WebServices.IMyService" /> </service>

</services>

<extensions> <behaviorExtensions>

<!-- This extension if for the WCF Error Handling--> <add name="ErrorHandlerBehavior"

type="WebServices.BehaviorsAndInspectors.ErrorHandlerExtensionBehavior, WebServices, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

</behaviorExtensions> </extensions>

<behaviors> <serviceBehaviors>

<behavior>

<serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> <ErrorHandlerBehavior />

</behavior> </serviceBehaviors>

</behaviors>

....

</system.serviceModel>

...

Here are a few links that may be helpful on this topic: https://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler(v=vs.100).aspx

http://www.brainthud.com/cards/5218/25441/which-four-behavior-interfaces-exist-for-interacting-with-a-service-or- client-description-what-methods-do-they-implement-and

Other Examples:

IErrorHandler returning wrong message body when HTTP status code is 401 Unauthorized IErrorHandler doesn't seem to be handling my errors in WCF .. any ideas?

How to make custom WCF error handler return JSON response with non-OK http code?

How do you set the Content-Type header for an HttpClient request?

Section 76.11: Using the exception object

You are allowed to create and throw exceptions in your own code. Instantiating an exception is done the same way that any other C# object.

GoalKicker.com – C# Notes for Professionals

460

Exception ex = new Exception();

// constructor with an overload that takes a message string

Exception ex = new Exception("Error message");

You can then use the throw keyword to raise the exception:

try

{

throw new Exception("Error");

}

catch (Exception ex)

{

Console.Write(ex.Message); // Logs 'Error' to the output window

}

Note: If you're throwing a new exception inside a catch block, ensure that the original exception is passed as "inner exception", e.g.

void DoSomething()

{

int b=1; int c=5; try

{

var a = 1; b = a - 1; c = a / b; a = a / c;

}

catch (DivideByZeroException dEx) when (b==0)

{

// we're throwing the same kind of exception

throw new DivideByZeroException("Cannot divide by b because it is zero", dEx);

}

catch (DivideByZeroException dEx) when (c==0)

{

// we're throwing the same kind of exception

throw new DivideByZeroException("Cannot divide by c because it is zero", dEx);

}

}

void Main()

{

try

{

DoSomething();

}

catch (Exception ex)

{

// Logs full error information (incl. inner exception)

Console.Write(ex.ToString());

}

}

In this case it is assumed that the exception cannot be handled but some useful information is added to the message (and the original exception can still be accessed via ex.InnerException by an outer exception block).

It will show something like:

GoalKicker.com – C# Notes for Professionals

461