Skip to content

pallu/raml-dotnet-tools

Repository files navigation

RAML Tools for .NET

The RAML Tools for .NET allows developers to easily integrate and consume APIs that expose a RAML definition, or create a new ASP.NET Web API implementation using a contract-first approach from a previously created RAML definition. See http://raml.org for information on RAML (RESTful API Markup Language).

The tools are provided as a Visual Studio extension, allowing simple and natural integration of RAML into a normal development workflow.

A single installation package provides support for both client and service code-generation scenarios.

Supported Scenarios

API Client Code from a RAML Definition

You can generate API client code from a RAML definition, which lets client applications consume existing APIs from a RAML definition.

In Visual Studio .NET, you can add a reference to a RAML definition, and a strongly-typed client proxy is generated in the project. A local copy of the RAML definition stores as a file within the Visual Studio project, which is kept in sync with the original RAML definition.

If the remote API does not provide a RAML definition, you can use a self-managed local definition to allow rapid generation of the client code in a declarative manner.

ASP .NET Web API Implementation from a RAML Definition

You can generate an ASP .NET Web API implementation from a RAML definition, which lets you create a new ASP .NET Web API from a new or existing RAML definition.

From within Visual Studio .NET, you can add a RAML definition from which the tool generates an initial ASP .NET Web API implementation. This implementation includes controller classes and route registrations that map to the resources exposed in the RAML definition and also includes model classes for their representation. The model classes are generated from the available JSON schemas.

In code, the Web API definition and implementation are logically separated. The generated code representing the definition is driven by the RAML definition allowing you to focus exclusively on the implementation classes. This separation of concerns allows iterative evolution of the API with non-destructive forward engineering of the code-based definition.

As a convenience, a local endpoint is registered to provides a browser-accessible API Console for the RAML-enabled implementation. This gives an easily navigable view of the API, including full documentation of routes, resource schema, and includes examples.

Prerequisites

  • Visual Studio 2013 Update 3

  • .NET Framework 4.5 or higher

  • RAML 0.8 compatible endpoint

  • Supported languages: C# (other languages indirectly)

Installation

  1. Run the RAML tools for Visual Studio Tools extension (VSIX) included in this package (ensure that Visual Studio 2013 is closed).

  2. On the initial screen select Visual Studio 2013 and click Install.

    RAML NET VSIXInstaller
  3. Wait for the installer to complete and click the Close button.

Generating an API Client

  1. Start Visual Studio 2013 and create a new project that consumes the API, or open an existing project.

  2. In the Solution Explorer right-click the References node for the selected project and select the Add RAML Reference command.

    RAML NET SolutionExplorer
  3. Specify the URL of the RAML definition and click the Go button, or use the Browse button to select the file from the local filesystem.

    RAML NET AddRAMLReference
  4. The RAML definition is presented together a preview of the available resources. When ready, click the OK button to begin generating the API client. Optionally change the filename or namespace for the generated code.

    A folder called API References containing the generated assets is added to the project. These assets include the original RAML file as well as any include dependencies, generated code, and a hidden .ref file with metadata for the code-generation tools.

    RAML NET APIRef

    The Newtonsoft.Json and Microsoft.AspNet.WebApi.Client NuGet packages are installed and referenced by the project.

  5. The C# classes nested beneath the parent RAML file contain the generated code to consume the Web API. At this point, the generated code is ready to be used.

Updating the API Reference

If the referenced RAML definition changes, the client code can be easily regenerated by right-clicking the parent RAML file and selecting Update RAML Reference.

RAML NET RunTests

Using the API Client with the Movies Sample

The RAML .NET installation package includes a sample project for a Movies API, which is a fictitious video library service where users browse a movie catalog, rent or return movies, and add movies to a wishlist for future watching.

The main constructor of the project’s MoviesAPI client uses an endpoint URI. The overload for the constructor allows a custom HttpClient implementation to be injected, such as an HttpClient instance configured with a MessageHandler. You can use this instance for unit testing.

C#: Consuming an API

The MoviesApi model object replicates the same structure as the RAML definition through available resources and actions. The methods in this object model are asynchronous and based on the Task Parallel Library (TPL), so they can executed with the new async and await syntax in C# version 5.

var api = new MoviesApi("http://movies.com/api/");

// GET /movies
var moviesResponse = await api.Movies.Get();

// GET /movies/available
var availableMoviesResponse = await api.Movies.Available.Get();

If your API requires authentication, you can specify the access token as per this example of an authenticated Post.

C#: Calling an Authenticated API with OAuth

If your API is secured with OAuth, you can specify the access token before making a call as it is shown in this example:

var api = new MoviesApi("http://movies.con/api/");
var postMovie = new PostMovies
{
  Name = "Big Fish",
  Director = "Tim Burton",
  Cast = "Ewan McGregor, Albert Finney, Billy Crudup",
  Language = "English",
  Genre = "Drama, Fantasy"
};

// Set OAuth access token
moviesApi.OAuthAccessToken = "<OAuth_Token>";

// POST /movies
var response = await moviesApi.Movies.Post(postMovie);

Replace the <OAuth_Token> with your OAuth token received from your OAuth authorization service.

C#: Consuming the HTTP Response

All methods in the generated class return a concrete implementation of ApiResponse base class. This class provides access to the HTTP status codes, raw headers, and content. The following code fragment illustrates how to use those:

var statusCode = response.StatusCode;
var rawHeaders = response.RawHeaders;
var rawContent = response.RawContent;
var stream = await response.RawContent.ReadAsStreamAsync();

When the RAML specifies a JSON contract for a response, the tool generates a strongly typed object with an equivalent structure. This object is accessible through the Content property in the response.

var moviesResponse = await api.Movies.Get();
MoviesGetOKResponseContent[] movies = moviesResponse.Content;
var director = movies.First().Director;

For more advanced scenarios in which several JSON schemas are associated with a response, the Content property provides a different typed object for each schema.

var okContent = movieResponse.Content.IdGetOKResponseContent;

var badReqContent = movieResponse.Content.IdGetBadRequestResponseContent;

var notFoundContent = movieResponse.Content.IdGetNotFoundResponseContent;

Depending on the HTTP status code, each property has a value or is null. For example, if the status code is OK (200), only the IdGetOKResponseContent has a value, and the other properties are null.

The response also provides access to typed headers in case they were included in the RAML definition:

GetByIdMoviesOKResponseHeader headers = movieResponse.Headers;
var created = headers.Created;
var code = headers.Code;

Implementing an ASP.NET Web API

To implement an ASP.NET Web API:

  1. Start Visual Studio 2013 and create a new ASP.NET Web project.

  2. In the New ASP.NET Project menu, click Web API:

    RAML NET NewASPProject
  3. In the Solution Explorer, right-click the project node and click the Add RAML Contract command.

    RAML NETAddRAMLContract
  4. The dialog lets you create a RAML definition or import an existing one. If you import an existing one, click the Go button to download the RAML definition from an URL, or browse to use a local copy from your file system. Optionally change the filename or namespace for the generated code.

    RAML NETAddRAMLContractScreen
  5. A Contracts folder is added to the project containing the generated assets. These assets include a local copy of the RAML definition, the generated model classes (inferred from the JSON schemas in the RAML definition), and .NET interfaces representing the contracts for the ASP.NET Web API Controllers. The controllers are generated in the Controllers folder, and implement the contract interfaces.

Updating the ASP.NET Web API

The tool also supports updating the generated ASP.NET Web API when a change is made to the RAML definition. This lets you keep the contract definition in a RAML file with the implementation, both staying in sync. Right-click the RAML contract file under Contracts, and select the option Implement RAML Contract. This command only affects the existing .NET contract interfaces and adds ASP.NET Web API controller implementations for any new resource in the RAML definition. The existing controller implementations remain untouched.

Implementing a Controller in ASP.NET Web API

The generated controllers provide the starting point for the implementation. The tool generates a class that implements the .NET interface or contract for the resource defined in RAML. The following example illustrates the controller Movies for the Movies RAML file:

public partial class MoviesController : IMoviesController
    {


        public IHttpActionResult Get()
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult Post(Models.MoviesPostRequestContent moviespostrequestcontent,[FromUri] string access_token = null)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult GetById([FromUri] string id)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult Put(Models.IdPutRequestContent idputrequestcontent,[FromUri] string id)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult Delete([FromUri] string id)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult PutRent(string json,[FromUri] string id,[FromUri] string access_token = null)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult PutReturn(string json,[FromUri] string id,[FromUri] string access_token = null)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult GetWishlist([FromUri] string access_token = null)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult PostById(string json,[FromUri] string id,[FromUri] string access_token = null)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult DeleteById([FromUri] string id,[FromUri] string access_token = null)
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult GetRented()
        {
            // Put your code here
            return Ok();
        }


        public IHttpActionResult GetAvailable()
        {
            // Put your code here
            return Ok();
        }

    }

The IMovies interface implemented by the controller represents the contract. You can provide, for example, the implementation code for the Get method and return a list of available movies in the catalog.

FAQ

Q: What are the differences between the RAML Parser for .NET and RAML Tools for .NET?

A: The RAML Parser takes a text based RAML definition and returns an Abstract Syntax Tree (An object model representing the resources/methods in the RAML definition). The RAML Tools leverage this model in code generation templates to provide strongly typed classes for the consumption or implementation of the API itself.

Q: Which languages can the tools generate code for?

A: Currently, C# is the only output language supported. This generated code can however simply be contained within a separate assembly, and the types exposed then consumed from any CLR language.

Q: Can I customize the code-generation templates?

A: RAML Tools for .NET uses T4 templates for code generation of client and service implementation. These templates are currently global for all projects, and are stored in a randomly named directory under the directory:

%UserProfile%\AppData\Local\Microsoft\VisualStudio\12.0\Extensions

While it is possible to customize the T4 templates found beneath this directory, it is not explicitly supported by the tooling yet and as such the naming and use of these templates is subject to change in future revisions. It is intended that explicit overriding on a per-project basis is supported in the near term.

Q: I already have an API built using ASP.NET WebApi - how do I adopt RAML for my project?

A: The reverse engineering scenario is under development, and is released soon. This allows you to extract a RAML definition for an existing WebApi project, allowing consumers of your API to quickly generate a client using the RAML Tools.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published