Web Api 2 Without MVC

Download full source code.

When building a Web Api 2 application there is much unneeded MVC baggage that comes along with it.

To start with all the css, html and javascript can go, then most of the packages, most of referenced dlls and almost all the C#.

Here are side by side comparisons of what you get and what you need.

All you really need for Web Api 2 is is the Global.asax to call WebApiConfig.Register which sets up the default routes and then a controller to perform an action.

Global.asax

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }
}

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

ValuesController.cs

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] {$"Guid 1: {Guid.NewGuid()}", $"Guid 2: {Guid.NewGuid()}" };
    }
}

Web API 2 Controller with multiple GET methods – part 2

I have two other posts on multiple GET methods, one for ASP.NET 5 Web Api, and another for Web Api 2.

Download full source code.

A few months ago I wrote a post explaining how to create a controller with multiple GET methods.
In that I used the combination of [RoutePrefix..] and [Route...] to generate routes like

  • http://…/api/values/geta
  • http://…/api/values/getb

Attribute parameter names and type

In this post I will show a different way of achieving multiple GETs by matching the type of parameter passed to the controller with the appropriate method.

In the first example I will match a method to an int being passed in, note the [Route("{id:int}")], this specifies that the expected parameter is named “id” and is an int.

// GET api/values/7
[Route("{id:int}")]
public string Get(int id)
{
    return $"You entered an int - {id}";
}

It is no problem to add another GET method with a [Route("{id:Guid}")]. This works fine because there is no way and int and Guid can be confused.

// GET api/values/AAC1FB7B-978B-4C39-A90D-271A031BFE5D
[Route("{id:Guid}")]
public string Get(Guid id)
{
    return $"You entered a GUID - {id}";
}

Where we start having problems is when the attribute routing system can’t determine which method you were attempting to call because it can’t distinguish an int from a long (or a string, decimal etc.)

For example, if we had another GET method taking a long, it would cause many runtime errors.

// GET api/values/8 - this will not work because it could be an int or a long
// GET api/values/4147483647 - this works because it can ONLY be a long
[Route("{id:long}")]
public string Get(long id)
{
    return $"You entered an long - {id}";
}

If we called http://...api/values/8, the attribute routing system has no way of knowing whether the GET method for the int or the long should be called.

But if we called http://...api/values/4147483647, that number is larger than an int can hold, the attribute routing system knows only one method matches the call.

If you want to have longs and ints in the same controller one of the routes needs to be altered. Note the new route – [Route("large/{id:long}")].

To call it now use http://...api/values/large/8 or http://...api/values/large/4147483647

[Route("large/{id:long}")]
public string Get(long id)
{
    return $"You entered an long - {id}";
}

Download full source code.

Downloading an in-memory file using Web Api 2

Download full source code

At first you think it’s going to be easy to download a file from Web Api, but as I discovered, it was not.

In my case I wanted to load data from the database, perform some processing and return a subset of the data as a file. This meant I needed to send something that was in memory back to the caller as a file; I was NOT loading a file from the disk.

For simplicity I will skip all the database work and processing and jump to the in-memory object and how to return that.

The code is fairly self explanatory.

using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Web.Http;
using System.Web.Http.Results;

namespace WebApi2DownloadInMemoryFile.Controllers
{
    public class FileDownloadController : ApiController
    {
        public IHttpActionResult Get()
        {
            string someTextToSendAsAFile = "Hello world";
            byte[] textAsBytes = Encoding.Unicode.GetBytes(someTextToSendAsAFile);

            MemoryStream stream = new MemoryStream(textAsBytes);

            HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StreamContent(stream)
            };
            httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "WebApi2GeneratedFile.txt"
            };
            httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

            ResponseMessageResult responseMessageResult = ResponseMessage(httpResponseMessage);
            return responseMessageResult;
        }
    }
}

Download full source code

Fluent Validation with Web Api 2

Full source code here.

I wrote blog post in 2015 on using the Fluent Validation NuGet package for complex validation needs. In the post the validator checked that a create person request had at least one active primary phone and at least one active primary email. Using Fluent Validation this was easy.

The blog post used a simple console application, but I now realize that a lot of people are having difficulty using this in Web API, especially when they have to consume the response from Web Api and look for potential errors from the Fluent Validation package.

I see an approach put forward Matthew Jones, but I don’t like the response rewriting. If you are making a request to a Web Api for a Person, you are no longer getting a Person, you’re getting a ResponsePackage with Person as an object inside. It causes problems with testing – calling the action method directly from a test return a different object then when called via a web request.

public class ResponsePackage  
{
    public List Errors { get; set; }

    public object Result { get; set; } 
}

This requires quite a bit of extra work on the client side to get at the Result object. Testing is also complicated because a test calling the action method directly get a different response than a request being rewritten.
The rewriting also applies to all responses from the WebApi.

I propose a slightly different solution.

Step 1

Add the FluentValidation.WebApi NuGet package to the Web Api project and wire it up in the WebApiConfig class.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //Fluent Validation
        config.Filters.Add(new ValidateModelStateFilter());
        FluentValidationModelValidatorProvider.Configure(config);
        
        //snip..    
    }
}
Step 2

Create a model and validator in a Models project.

[Validator(typeof(PersonCreateRequestModelValidator))] 
public class PersonCreateRequestModel
{
    public Guid PersonId { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}
	
public class PersonCreateRequestModelValidator : AbstractValidator
{
    //Simple validator that checks for values in Firstname and Lastname
    public PersonCreateRequestModelValidator()
    {
        RuleFor(r => r.Firstname).NotEmpty();
        RuleFor(r => r.Lastname).NotEmpty();
    }
}

Step 3

Create the Web Api endpoint.

public IHttpActionResult Post([FromBody]PersonCreateRequestModel requestModel)
{
    // If we get this far we have a vaild model.
    // If we then saved the person to the database we would get an id for the person and return it to the caller.
    requestModel.PersonId = Guid.NewGuid();

    return Ok(requestModel.PersonId);
}
Step 4

Create a client to call the Web Api endpoints. In my example I use a console app, but you could use MVC or another Web Api project.

Create a HttpClient client to call the web service.

private HttpClient GetHttpClient()
{
    var httpClient = new HttpClient();
    httpClient.BaseAddress = new Uri(@"http://localhost:5802/api/");
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    return httpClient;
}

Call the web service using the client and examine the response for success, HttpStatusCode.OK, or failure, any other status code.

private async <Task> PostToService(PersonCreateRequestModel model)
{
    var httpClient = GetHttpClient();
    string requestEndpoint = "person"; // full request will be http://localhost:5802/api/person
    HttpResponseMessage response = await httpClient.PostAsJsonAsync(requestEndpoint, model);

    WebApiResponse wrappedResponse;
    
    if (response.StatusCode == HttpStatusCode.OK)
    {
        var id = await response.Content.ReadAsAsync();
        wrappedResponse = new WebApiResponse(id, response.StatusCode);
    }
    else
    {
        var errors = await response.Content.ReadAsStringAsync();
        wrappedResponse = new WebApiResponse(errors, response.StatusCode, true);
    }
    return wrappedResponse;
}

Success or failure, I wrap the repsonse (in the client) without losing anything from the web service. WebApiResponse is a generic class and as such takes any type. The wrapped response is then returned to the caller to do with as they wish.

public class WebApiResponse
{
    public WebApiResponse(T apiResponse, HttpStatusCode httpStatusCode)
    {
        ApiResponse = apiResponse;
        HttpStatusCode = httpStatusCode;
    }

    public WebApiResponse(string error, HttpStatusCode httpStatusCode, bool isError) // isError is just a way to differentiate the two constructors. If <code>T</code> were a string this constructor would always be called. 
    {
        Error = error;
        HttpStatusCode = httpStatusCode;
    }
    public T ApiResponse { get; set; }
    public HttpStatusCode HttpStatusCode { get; set; }
    public string Error { get; set; }
}

The major benefits I see in the approach are that it is simple, very flexible, does not change anything coming back from the web service, testing is unaffected, and you are altering the Microsoft provided response pipeline.

Full source code here.

Web API 2 Controller with multiple get methods

I have two other posts on multiple GET methods, one for ASP.NET 5 Web Api, and another for Web Api 2.

It seems that every version of Web API changes how it handles default routes or route prefixes or whatever the next name will be.

I’ve written previously on how to handle multiple get methods in Asp.Net 5 Web API.

It’s a little different in Web Api 2.

using System.Web.Http;

namespace WebApiMultipleGets.Controllers
{
    [RoutePrefix("api/values")]
    public class ValuesController : ApiController
    {
        public string Get()
        {
            return "simple get";
        }

        [Route("geta")]
        public string GetA()
        {
            return "A";
        }

        [Route("getb")]
        public string GetB()
        {
            return "B";
        }

        [Route("getc")]
        public string GetC()
        {
            return "C";
        }

        [Route("getd")]
        public string GetD()
        {
            return "D";
        }
    }
}

Value cannot be null. Parameter name: constructor

Using Entity Framework I occasionally get the following error when reading from the database –
exceptionMessage=Value cannot be null.
Parameter name: constructor

My Person class looked like this –

    public class Person
    {
        public Person(string firstname, string lastname)
        {
             Firstname = firstname;
             Lastname = lastname;
        }

        public Guid PersonId { get; set; } 
        public string Firstname { get; set; } 
        public string Lastname { get; set; } 
        public DateTime SomeDate { get; set; }
     }

There is no way for Entity Framework to know how to instantiate this object because there is no empty constructor.

If you are following some of the principles of domain driven design you may not want a public empty constructor, no problem, make it private.

    public class Person
    {
        private Person(){} // Entity Framework queries will work now

        public Person(string firstname, string lastname)
        {
             Firstname = firstname;
             Lastname = lastname;
        }

        public Guid PersonId { get; set; } 
        public string Firstname { get; set; } 
        public string Lastname { get; set; } 
        public DateTime SomeDate { get; set; }
     }

Locating and checking an executing DLL on a running web server or other application

Edit – even though the steps described below related to an example with IIS, you can use this technique for any running process, it’s just a matter of identifying the process id. In some cases you will not even need the process id, e.g. if all processes are using the same version of a DLL.

Introduction

Figuring out what dll is actually executing on a running web server is no easy task; it’s not as simple as looking in the bin directory of the deployed application as the dlls are copied from there to a set of temporary directories within the windows systemroot.

I know of two ways of figuring this out, the first requires some code changes and the second does not.

I wrote some time ago about how to find which dll is really executing when running an application, it works just fine if you can alter the source code to include the snippet I proposed.

Clearly that is not a lot of use in a deployed application when you cannot change the code or even redeploy.

No code change needed

Here is the alternative, no code changes needed. The application I am interested in is called MyFancyApp, there are other applications running on the server too. Let’s say that the dll I am interested in is AutoMapper.dll, I need to verify that the running dll is really the version I expect.

1. Open a command prompt and navigate to %systemroot%\System32\inetsrv.
2. Execute appcmd list wp, this will show all the running application pools and the associated process ids. The output will look something like this –
find dll appcmd

You can see that MyFancyApp is running with process id of 1224.

Now switch to Process Explorer.

3. Open Process Explorer and hit CTRL-F, type in AutoMapper.dll. In the results PID 1224 is shown, in fact it will be there a few times. At this point the file location of the dll is visible.
find dll search

4. Double click one of the entries for PID 1224 where the Type is DLL.

5. In the lower pane of Process Explorer the AutoMapper.dll is selected and the version is shown, I had to right click on the lower pane and the version column to make it visible.

find dll results

That’s it. No redeploy, no code editing, no remote debugging. You now know for sure which dll is running and where to find it. If the dll is your own and you are concerned about what might be in the code you can open the file in dotpeek to decompile it.

Entity Framework Core and calling a stored procedure

Download full source code here.

I thought this would be easy, there is a method called ExecuteSqlCommand which takes the stored proc name and an array of parameters. I wanted to pass in two parameters and get one back, no problem, I’ve done this with ADO.Net and Entity Framework 6.

But holy s**t, two hours later and it was nowhere near working and I was very annoyed. ExecuteSqlCommand takes SqlParameters and the constructor for the output parameter is way more confusing than it needs to be. The input SqlParameter takes a name, a type and a value but the output SqlParameter needs eight more constructor params!!

Fortunately, EF Core still supports old style commands –

            DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();

DbCommand still has the ExecuteNonQueryAsync method. Save yourself a major headache and use the cmd.ExecuteNonQueryAsync().

Here is a simple example passing in two parameters and getting one output back.

using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Threading.Tasks;
using Microsoft.Data.Entity;
using Nito.AsyncEx;

private async Task ExecuteStoredProc()
{
	DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();

	cmd.CommandText = "dbo.sp_DoSomething";
	cmd.CommandType = CommandType.StoredProcedure;

	cmd.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar) { Value = "Steve" });
	cmd.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar) { Value = "Smith" });

	cmd.Parameters.Add(new SqlParameter("@id", SqlDbType.BigInt) { Direction = ParameterDirection.Output });

	if (cmd.Connection.State != ConnectionState.Open)
	{
		cmd.Connection.Open();
	}

	await cmd.ExecuteNonQueryAsync();

	long id = (long)cmd.Parameters["@Id"].Value;
}

Download full source code here.

Getting Web API Exception Details from a HttpResponseMessage

The Problem

It’s hard to get the details of an exception from a Web Api response when calling Web Api from a C# program. (Skip to the solution if you don’t care about the background), it even handle inner exceptions!

Some background

If you are working on a Web Api project and testing with a web browser you get a wonderful error page when an exception occurs. It gives you the message, exception message, exception type and the stack trace. Pretty much all you need to get started figuring out what has gone wrong.
Exception in browser

Same thing with fiddler, get a 500 back and you’ll even be treated to a Json version of the above.

Exception in fiddler

What about calling the action method from inside a c# program? Should be easy, you just create a client, setup the query, let it rip and examine the response for a success status and then read the content to get the returned values. Great, works fine.

What if the server threw an exception like the ones shown above, I thought it would be a simple thing to call response.Exception or the like and get all the details. But easy it is not.
I rooted around in the response for a while but found nothing that was simple to use.

The Solution

Instead I have added an extension method to HttpResponseMessage to parse the details of the exception from the Json in the response.Content.

using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace SimpleWebApiClient
{
    public static class HttpResponseMessageExtension
    {
        public static async Task<ExceptionResponse> ExceptionResponse(this HttpResponseMessage httpResponseMessage)
        {
            string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
            ExceptionResponse exceptionResponse = JsonConvert.DeserializeObject<ExceptionResponse>(responseContent);
            return exceptionResponse;
        }
    }

    public class ExceptionResponse
    {
        public string Message { get; set; }
        public string ExceptionMessage { get; set; }
        public string ExceptionType { get; set; }
        public string StackTrace { get; set; }
        public ExceptionResponse InnerException { get; set; }
    }
}

Usage is simple.

    //snip
    HttpResponseMessage response = await httpClient.GetAsync(query).ConfigureAwait(false);
    
    if (response.IsSuccessStatusCode)
        // return the value
    
    // But if an error occurred read the details           
    ExceptionResponse exceptionResponse = response.ExceptionResponse();

    //snip

 

Cached nuget packages causing you problems?

Short version
If you are having problems with nuget packages and think it might be related to local caching delete packages from these directories –

%LocalAppData%\NuGet\Cache
and
%userprofile%\.nuget\packages\

Long version
I was making nuget package, lets call it Foo, for my own use, not one that I was going to distribute publicly, but I was putting in on MyGet.

I had a few classes in it and after making the nuget package, I uploaded it to MyGet. I then switched to the Business solution and referenced this newly created nuget package.

After doing a little bit of work, I noticed that I had incorrectly made a class internal rather than public in the Foo nuget package.

No problem, back to the Foo solution where I was making the library, change the class to public, rebuild, and remake the nuget package. I didn’t want to increment the version number, so I left it at 1.0.0. On MyGet I deleted the old package and then uploaded the new one.

Here’s what I tried and didn’t work –

  • In the Business solution referencing the Foo nuget package, I uninstalled Foo and then reinstalled it.
  • But Visual Studio still reported that the class was inaccessible!
  • Uninstall and reinstall again, same problem!!
  • Delete the Foo directory from the packages directory beside the solution file, remove the Foo line from the packages.config. Reinstall Foo. Same problem!!!
  • Recomplie Foo, delete Foo from MyGet, reupload Foo to MyGet. Reinstall Foo. Still inaccessible!!!!
  • WTF!!!!!

And this is what works –

  • Download the Foo nuget package directly from MyGet and reference it directly. Success! There must be a local cache that Visual Studio is using!!!!!!

Yes there are, I found two –

%LocalAppData%\NuGet\Cache
and
%userprofile%\.nuget\packages\

Delete the offending nuget package; back in Visual Studio I can now successfully install the nuget package.

In general avoid using the same package version number when uploading a new package to MyGet.