C# Very simple REST server

How to build a simple REST server in C#.

Main challenge was to bend C# web application to comply with the request and the response in the structure I wanted it to be.

If you want to skip my explanations, all the code is here: https://github.com/tan-tan-kanarek/csharp-rest-server-example

  1. Application configuration – WebApiConfig
First I defined the mapping to the different controllers types.
Routing path to all standard controllers using service and action in the path:

config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/service/{controller}/action/{action}"
            );

Routing path to multi-request controller:

config.Routes.MapHttpRoute(
                name: "Multirequest",
                routeTemplate: "api/service/multirequest",
                defaults: new { Controller = "multirequest" }
            );

Routing path to root, where scheme XML should be returned:

config.Routes.MapHttpRoute(
                name: "Scheme",
                routeTemplate: "",
                defaults: new { Controller = "scheme" }
            );

Next I defined request parser to translate the JSON request into my objects types:

config.Filters.Add(new RequestParser());

And response handlers to wrap the results with my own structure:

config.Filters.Add(new ErrorHandler());
config.MessageHandlers.Add(new WrappingHandler());

Last thing I set the XML serializer settings:

List knownTypes = Assembly.GetExecutingAssembly().GetTypes().Where(type => typeof(IRestObject).IsAssignableFrom(type) && !type.IsGenericType).ToList();
            knownTypes.Add(typeof(RestResponseList));

XmlObjectSerializer xmlSerializer = new DataContractSerializer(typeof(RestResponse), knownTypes);
config.Formatters.XmlFormatter.SetSerializer(xmlSerializer);

config.Formatters.XmlFormatter.SetSerializer(new XmlSerializer(typeof(SchemeController.Scheme)));

config.Formatters.XmlFormatter.WriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates;

  2. Example users controller – UserController
User controller, like any controller in C# must implement ApiController and for my own marking to know it’s a standard controller, I marked it also as IRestController.

public class UserController : ApiController, IRestController
{
}

In order to specify action name for each method, I just added ActionName attribute:

[ActionName("add"), HttpPost]
public User Add([ValueProvider] User user)
{
    return user.Add();
}

Note the [ValueProvider] attribute that means that I will parse the POST body and will provide the value for user object, I do that in the RequestParser.

  3. Request parser – RequestParser
By implementing ActionFilterAttribute.OnActionExecuting I can manipulate the methods inputs, in my case I parse the JSON that I extracted from actionContext.Request.Content, then I go through the method arguments using actionContext.ActionDescriptor.ActionBinding.ParameterBindings and deserialize each argument from JSON object into the expected argument type.

  4. Data model – User
Each object in the data model must extend RestObject and define DataContract attribute, while each property must define the DataMember attribute, both for XML and JSON serialization.
I also used the same object to map the properties to the database using RestTable and RestColumn attributes.

[DataContract(Namespace = "")]
[RestTable("users")]
public class User : RestPersistentObject
{
    public User()
        : base()
    {
    }

    public User(long id)
        : base(id)
    {
    }

    protected override void SetDefaults()
    {
        base.SetDefaults();
        Status = UserStatus.ACTIVE;
    }

    [DataMember(Name = "firstName")]
    [RestColumn("first_name")]
	public string FirstName { get; set; }

    [DataMember(Name = "lastName")]
    [RestColumn("last_name")]
	public string LastName { get; set; }

    [DataMember(Name = "status")]
	public UserStatus? Status { get; set; }
}

Note that extending RestPersistentObject gives me id, created-at and updated-at properties.

  5. Multi-request – MultirequestController
Multi-request controller enables series of requests, that can save the HTTP round-trip in case you want to execute several requests together.
Note that this controller force me to have flat list of services, it simplifies the routing URLs as well as the server code.

Leave a Reply

Your email address will not be published. Required fields are marked *