Skip to content

An abstract implementation of Peasy.IDataProxy that communicates with HTTP services

License

Notifications You must be signed in to change notification settings

peasy/Peasy.DataProxy.Http

Repository files navigation

peasy

Peasy.DataProxy.Http

Peasy.DataProxy.Http provides the HttpServiceProxyBase class. HttpServiceProxyBase is an abstract class that implements IDataProxy, and can be used to very quickly and easily provide a data proxy that communicates with HTTP services via the GET, POST, PUT, and DELETE verbs.

Where can I get it?

First, install NuGet. Then create a project for your HTTP class implementations to live. Finally, install Peasy.DataProxy.Http from the package manager console:

PM> Install-Package Peasy.DataProxy.Http

You can also download and add the Peasy.DataProxy.Http project to your solution and set references where applicable

Creating a concrete HTTP data proxy

To create an HTTP repository, you must inherit from HttpServiceProxyBase. There is one contractual obligation to fullfill.

1.) Override RequestUri - this property represents the endpoint your proxy implementation will communicate with

Here is a sample implementation

public class PersonRepository : HttpServiceProxyBase<Person, int>
{
    protected override string RequestUri
    {
        get
        {
            return "http://localhost:1234/api/people";
        }
    }
}

In this example, we create an HTTP person repository. The first thing to note is that we supplied Person and int as our generic types. The Person class is a DTO that must implement IDomainObject<T>. The int specifies the key type that will be used for all of our arguments to the IDataProxy methods.

As part of our contractual obligation, we override RequestUri to provide the endpoint in which the data proxy will communicate with. In this example, we hard coded the uri for brevity. In practice, you will most likely return a value from a configuration file or similar.

By simply inheriting from HttpServiceProxyBase and overriding RequestUri, you have a full-blown HTTP data proxy that communicates with an HTTP endpoint, handling the serialization/deserialization of your types, and throwing peasy specific exceptions based on HTTP error response codes.

Serialization/Deserialization

By default, HttpServiceProxyBase was designed to communicate with HTTP endpoints by sending and consuming JSON payloads. Your strongly typed DTOs will be serialized as JSON before being sent to HTTP endpoints. In addition, returned JSON from HTTP endpoints will be deserialized into strongly typed DTOs and returned from your HTTP data proxy methods.

There might be cases when your HTTP data proxy needs to communicate with a service using a different media type, such as XML or a custom defined media type. In this case, you can specify your own MediaTypeFormatter by overriding the GetMediaTypeFormatter method.

Here is an example

public class PersonRepository : HttpServiceProxyBase<Person, int>
{
    protected override string RequestUri
    {
        get
        {
            return "http://localhost:1234/api/people";
        }
    }
    
    protected override MediaTypeFormatter GetMediaTypeFormatter()
    {
        return new XmlMediaTypeFormatter();
    }
}

In this example, we simply override GetMediaTypeFormatter and return the XmlMediaTypeFormatter. Doing this will serialize and deserialize our types to and from XML.

Peasy specific exceptions

Your HTTP data proxy implementations serve as a data layer abstraction to your peasy service classes. As such, consumers of your data proxies should know how to handle certain exceptions that can happen when being consumed. HttpServiceProxyBase handles a few specific HTTP error response codes and throws specific peasy exceptions so that you can handle them accordingly.

ServiceException - This exception is thrown when an HTTP endpoint returns a 400 Bad Request error response. This response is typically returned when a business or validation rule is broken during an HTTP request. The command class catches exceptions of this type, and adds errors to the ExecutionResult.Errors list on your behalf.

DomainObjectNotFoundExeption- This exception is thrown when an HTTP endpoint returns a 404 Not Found error response. This response is typically returned when an item cannot be found during an HTTP request.

ConcurrencyException - This exception is thrown when an HTTP endpoint returns a 409 Conflict error response. This result is typically returned when a concurrency issue occurs during an HTTP request.

NotImplementedException - This exception is thrown when an HTTP endpoint returns a 501 Not Implemented error response. This result is typically returned when a requested resource provides no implementation for an HTTP request.

Parsing an error response message

Errors returned from HTTP endpoints can be formatted in many different ways. In order to parse the errors into a format that is suitable for your needs, you can simply override the OnFormatServerError, as displayed below:

public class PersonRepository : HttpServiceProxyBase<Person, int>
{
    protected override string RequestUri
    {
        get
        {
            return "http://localhost:1234/api/people";
        }
    }
    
    protected override string OnFormatServerError(string message)
    {
        var msg = message.Split(new[] { ':' })[1];
        Regex rgx = new Regex("[\\{\\}\"]"); // get rid of the quotes and braces
        msg = rgx.Replace(msg, "").Trim();
        return msg;
    }
}

Synchronous execution

Under the hood, HttpServiceProxyBase uses HttpClient for HTTP communications. HttpClient only exposes asynchronous functionality, however, IDataProxy exposes both synchronous and asynchronous operations. As a result, the synchronous methods of the HttpServiceProxyBase synchronously invoke the asychronous methods of HttpClient.

This situation can cause issues when invoked within different contexts, most notably within WPF and ASP.NET applications. This topic can be best explained here. To remedy any situations where invoking asynchronous methods synchronously cause issues, ISynchronousInvocationStrategy was developed to allow you to inject alternative ways to synchronously invoke the asynchronous methods of HttpClient.

Currently there are 2 concrete implementations of ISynchronousInvocationStrategy, which are RunWithinTaskStrategy and WaitForResultStrategy.

By default, HttpServiceProxyBase is configured to use WaitForResultStrategy. In the event that this strategy does not suit your needs, you can inject the RunWithinTaskStrategy or your own custom developed strategy.

About

An abstract implementation of Peasy.IDataProxy that communicates with HTTP services

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages