What is SimpleRest?

Put very simply, it is a .NET platform used to create REST services inspired by WCF Web API 0.6.0.0.  SimpleRest was designed to be extremely light weight, powerful, extensible, and very easy to use.  SimpleRest does not try to get cute or tricky with the code like other platforms tend to do but rather it employs a very simple methodology…  The KISS principle.  Simple is better.

Creating web API’s are becoming more and more common these days because of the obvious power that they can bring a business.  This means that the right technology can become very important and choosing the right one that suites your needs is something that is also very important.  Something to look for when choosing these technologies for your organization might be: Ease of use, ability to get something created quickly, maintainability, ability to support independent scaling of services, etc…  The good news is that SimpleRest was created with just these types of things in mind.  SimpleRest was created to address business needs and cater to developers writing business applications.

Why not just use ASP.NET MVC4 Web API?

As well as being positively inspired by WCF Web API 0.6.0.0 it was also inspired by ASP.NET MVC4 Web API in that ASP.NET MVC4 Web API is a true step backwards from WCF Web API 0.6.0.0 (in my opinion of course).

Some might ask the very obvious question, “why would I not just use ASP.NET MVC4 WebAPI for my web API’s?”.  Hell, its Microsoft and comes out of the box with MVC4 now so why wouldn’t you use it right?  I will admit that having a native “out of the box” platform that solves the problem that you are trying to solve is quite appealing but as your services start getting more mature and your knowledge of how your services should be created matures you will quickly find out that this platform is very limiting and might not operate as you think it should.  Maybe it is the lack of ability to create endpoints for particular sub-resources.  Maybe it is the confusing way that HttpRoute’s get registered.  Or maybe it is because simply creating a service requires THIRTY FIVE (35) assembly dependencies in your project to drive the platform.  Whatever your reason is that upsets you about the way ASP.NET MVC4 Web API does business it is clear that it does not Keep It Stupid Simple as it should.

Additionally, ASP.NET MVC4 Web API suggests that your web application can, and maybe should, live with your web API.  This is a very bad idea to suggest things like this as services living within the web application can become problematic for many reasons.  Separation of concerns is something that every developer should go out of their way to do so why would you use a platform that suggests that you should marry the concerns of web services and web applications?


 

What is What and what types do I need to know about to start?

SimpleRest.Core.ServiceAttribute

  • ·        Inherits System.Attribute.  This is an attribute put on a class that tells the SimpleRest platform that the class where this attribute exists is a service.
  • ·        Input Parameters:
    • Required: ServiceRoot (or route) – Determines the route for this service
    • Optional: MajorVersion – Determines what the major version is
    • Optional: MinorVersion – Determines what the minor version is
    • Optional: IgnoreVersionPrefix – Determines if the service should ignore version prefix upon registration.
  • ·        Behavior:
    • Upon registration of this service it will automatically prefix the route specified in ServiceRoot with a ‘v’ followed by the major version.  If the minor version was specified it is then followed by a dot (‘.’) and the minor version specified.  In the event that IgnoreVersionPrefix is set to true the version prefix will be ignored upon service registration.

SimpleRest.Core.WebGetAttribute

  • ·        Inherits System.Attribute and implements SimpleRest.Core.IWebInvokeAttribute.  Attribute put on a method that tells the SimpleRest platform that the method is an operation of a service.  This operation will only get registered as an operation if the class is adorned with the SimpleRest.Core.ServiceAttribute.
  • ·        Input Parameters:
    • Optional: UriTemplate – Determines the route for this operation.
  • ·        Behavior:
    • Upon registration of this operation this operation will be registered as the Service Route followed by the UriTemplate specified ‘<ServiceRoute>/<UriTemplate>’.  When this attribute is used this operation will only be routed to in the event that the http method on the request is GET.

SimpleRest.Core.WebHeadAttribute

  • ·        Inherits System.Attribute and implements SimpleRest.Core.IWebInvokeAttribute.  Attribute put on a method that tells the SimpleRest platform that the method is an operation of a service.  This operation will only get registered as an operation if the class is adorned with the SimpleRest.Core.ServiceAttribute.
  • ·        Input Parameters:
    • Optional: UriTemplate – Determines the route for this operation.
  • ·        Behavior:
    • Upon registration of this operation this operation will be registered as the Service Route followed by the UriTemplate specified ‘<ServiceRoute>/<UriTemplate>’.  When this attribute is used this operation will only be routed to in the event that the http method on the request is HEAD.

SimpleRest.Core.WebOptionsAttribute

  • ·        Inherits System.Attribute and implements SimpleRest.Core.IWebInvokeAttribute.  Attribute put on a method that tells the SimpleRest platform that the method is an operation of a service.  This operation will only get registered as an operation if the class is adorned with the SimpleRest.Core.ServiceAttribute.
  • ·        Input Parameters:
    • Optional: UriTemplate – Determines the route for this operation.
  • ·        Behavior:
    • Upon registration of this operation this operation will be registered as the Service Route followed by the UriTemplate specified ‘<ServiceRoute>/<UriTemplate>’.  When this attribute is used this operation will only be routed to in the event that the http method on the request is OPTIONS.

SimpleRest.Core.WebPostAttribute

  • ·        Inherits System.Attribute and implements SimpleRest.Core.IWebInvokeAttribute.  Attribute put on a method that tells the SimpleRest platform that the method is an operation of a service.  This operation will only get registered as an operation if the class is adorned with the SimpleRest.Core.ServiceAttribute.
  • ·        Input Parameters:
    • Optional: UriTemplate – Determines the route for this operation.
  • ·        Behavior:
    • Upon registration of this operation this operation will be registered as the Service Route followed by the UriTemplate specified ‘<ServiceRoute>/<UriTemplate>’.  When this attribute is used this operation will only be routed to in the event that the http method on the request is POST.

SimpleRest.Core.WebPutAttribute

  • ·        Inherits System.Attribute and implements SimpleRest.Core.IWebInvokeAttribute.  Attribute put on a method that tells the SimpleRest platform that the method is an operation of a service.  This operation will only get registered as an operation if the class is adorned with the SimpleRest.Core.ServiceAttribute.
  • ·        Input Parameters:
    • Optional: UriTemplate – Determines the route for this operation.
  • ·        Behavior:
    • Upon registration of this operation this operation will be registered as the Service Route followed by the UriTemplate specified ‘<ServiceRoute>/<UriTemplate>’.  When this attribute is used this operation will only be routed to in the event that the http method on the request is PUT.

SimpleRest.Core.ServiceDiscoveryFactory

  • ·        This class is where all services get registered.  All of the ways a service can be registered are located in this document and use this class to facilitate registration.
  • ·        Behavior:
    • Static class used to facilitate registration of services for the SimpleRest platform.  There are methods to register individual services and a method to scan assemblies and register services found therein.

SimpleRest.Core.HttpApplicationBase

  • ·        Inherits System.Web.HttpApplication.  Provides functionality so the developer can easily tap into the web start event and be provided event arguments that make service registration very easy.
  • ·        Behavior:
    • This class uses the Application_Start method to fire off the Initialize method which one must override.  The initialize in this context can be used the same as Application_Start.  Within your class do not override Application_Start as it will interfere with the initialize method call making it not fire appropriately.  This class also provides the developer with the ability to handle file extensions in their routing.  The built in routing framework (System.Web.Routing) does not like it when you include file extensions in your routes and does not route correctly.  This was remedied with a method that implements Application_BeginRequest and manually attempts to route the URI in the event that a file extension exists.  In the Implementing class do not override Application_BeginRequest() as it will not allow the file extension routing to work propertly.  You can turn the file extension routing on and off by setting the IsUriDotSuffixValid flag on the base class.  Examples of using this class can be found in this document.

There are many more classes within the SimpleRest project.  Feel free to browse them for a more in depth understanding of the pipeline.

Assemblies

SimpleRest.Core

This is the assembly that drives the SimpleRest platform.  With this single assembly you can create rest services using the SimpleRest platform.  This assembly was designed to be as light weight as possible only containing dependencies on the following .NET assemblies: Microsoft.CSharp, System, System.Web, System.Web.Routing.

This assembly does not contain any pre-defined media type formatters out of the box so any media type formatters you would like to use would need to be created and wired up to the Configuration object.  The SimpleRest.Core.Extensions assembly contains default media type formatters that you can choose to use if you wish.

This assembly wires up a default error handler for the developer which can be overridden within the configuration object.  The default behavior returns 501 (Not Implemented) if one of the following exceptions was thrown: NotImplementedException, InvalidOperationException, NotSupportedException.  The default behavior returns 400 (Bad Request) in any other circumstances.  The default error code is 400 (Bad Request) unless otherwise set in the error handler for any exceptions thrown throughout the SimpleRest pipeline execution.

SimpleRest.Serialization

This assembly was created to address any type of serialization problems or enhancements. 

This assembly contains an XSD serializer which will turn a System.Type into its associated XSD in string format.  This was created so that XSD’s could be supplied to developers consuming the service to better describe the resource that a particular endpoint is targeting. 

This assembly also contains a custom XML serializer which can be used in place of the Microsoft XML serializer.  The idea was to create a more verbose xml serializer while making it faster and easier to use.  The developer can choose to use this or to simply use another XML serializer.

SimpleRest.Core.Extensions

This assembly is still a light weight assembly but not as light weight as the SimpleRest.Core assembly.  This assembly contains dependencies on the following assemblies: Microsoft.CSharp, Newtonsoft.Json (Json.NET), System, System.Web, System.Web.Routing, System.Xml, SimpleRest.Core, SimpleRest.Serialization.

This assembly’s purpose is to extend the functionality of SimpleRest.Core.  The reason a new assembly was created to do this was so that the SimpleRest.Core assembly did not start getting polluted with code that did not concern the core SimpleRest pipeline functionality.  Because SimpleRest.Core provides many extensibility points SimpleRest.Core.Extensions can plug into those and provide additional value to developers such as automatic XSD route creation for each registered service and operation.

Simple Examples

Registering Services

Examples in downloadable documentation
 

Manually register individual services using event arguments using

Examples in downloadable documentation


Creating a Service

 Examples in downloadable documentation


Dependency Injection

Dependency injection can be accomplished very easily by setting a property on the associated service Configuration object called CreateServiceInstance.  CreateServiceInstance is always called when an instance of a service needs to be created.  This method provides the service type that needs to be created and allows for IoC containers to be used therein.

Example in downloadable documentation

Error Handling

There are two ways in which error handling can be accomplished using the SimpleRest pipeline.  The global way to handle all errors for a service is done by setting the ErrorHandler property on the Configuration object for an associated service.  All unhandled errors that occur during the SimpleRest request lifecycle will be funneled through this handler.  The error handler gives the developer visibility into the actual exception that was thrown, the http request, and the http response.  The developer can set response information for the content body, response headers, and status code here.

Example in downloadable documentation

Another way a developer can handle errors is on the service level itself rather than a global handler.  This is accomplished by inheriting SimpleRest.Core.Routing.ServiceBase on the associated service and overriding the OperationExecutionException method.  Visibility into the exception and the associated operation will be provided here and handling of the exception can occur.  It is important to understand that even though the error is handled here it will still be bubbled up to the ErrorHandler as well.

Example in downloadable documentation

SimpleRest.Core.Routing.ServiceBase

Visibility into Service Operation Execution?

When a service inherits SipelRest.Core.Routing it provides visibility into service specific operation execution.  It allows the developer to override three methods: OperationPreExecution, OperationPostExecution, and OperationExecutionException.  OperationPreExecution is a method that is invoked before any operation is invoked on that service giving visibility into the operation that is about to be invoked.  OperationPostExecution is a method that is after any operation is invoked on that service giving visibility into the operation that was invoked the value that is being returned.  The OperationExecutionException method is invoked in the event an operation throws an exception and gives visibility into the operation as well as the System.Exception that was thrown.  In the event a developer handles the OperationExecutionException it is important to know that the global ErrorHandler wired up for that service will still be invoked.

Registered Operations

Inheriting this class on a service gives visibility into which operations have been registered for the service and pieces of metadata.  This was done in the event the developer needed this information for any sort of reason.  This property is called RegisteredOperations and is read only.

A Reusable Service?

Because creating an instance of a service at runtime can be taxing for every single request this class gives the developer the opportunity to set a flag called IsReusable.  When this flag is set to true the SimpleRest pipeline will create a single instance of this service and cache it at the application level so that the next call to this service is pulled from cache instead of being instantiated.

Operation Mapping for Strongly Typed Objects

How would a developer allow for a custom complex type as an input parameter to the service operations?  It makes sense that there would be a way to handle this scenario so that creating this custom complex type is done in a single place rather than riddled throughout the code polluting it. 

When this class is inherited it gives the developer the opportunity to specify Operation Mapping Handlers by calling the AddMapping method.  This allows a developer to create functionality to map custom complex objects they create into input parameters for the service operations. 
To do this the developer creates a class and either inherits SimpleRest.Core.Routing.OperationMappingHandler or extends SimpleRest.Core.routing.IOperationMappingHandler.  These provide the developer with visibility into the http request and the operation being invoked in which they can use to formulate the complex object they wish to pump into the service operation.  The OutputParameterName is very important as this indicates what the input parameter name should be on the operation in which the object should be mapped. 

Example in downloadable documentation

Last edited Jan 12, 2013 at 6:06 PM by DotNetRockStar, version 3

Comments

No comments yet.