I wanted to take a closer look at a few new(ish) technologies like WebApi and TypeScript for some time now, and figure out how it will play along with angular and other js frameworks.
So here’s my little experiment. It’s a very basic app to create/list/update/delete products and product categories. Initially I also thought to have stores in there, but the code for that would be a pretty much a duplicate, so I didn’t bother.
And yeah, a part of this is new to me, so some decisions may not be the best, and you’re welcome to comment.
So let’s start with back end.
This is what an api controller looks like.
Few things to note:
GET method is marked with [Queryable(ResultLimit = 200)] attribute, and returns IQueryable. This is a gateway for OData. What you do here is basically transferring control over the data to output to the client. Say if you want to get Products named ‘banana’ you’ll ask like this:
/api/product/?$filter=Name eq ‘banana’
Note here is that property names are case-sensitive, that is “$filter=name eq ‘banana’” will fail.
Also, this operates on Queryable returned from database, so it has to support OData as well.. Which is sadly not quite the case with Raven, for example it would fail if you’ll ask for names starting with ‘b’ (?$filter=startswith(Name, ‘b’) eq true) – it’ll throw an exception
Could not understand how to translate ‘IIF(($it.Name == null), null, Convert($it.Name.StartsWith(“b”)))’ to a RavenDB query.
Are you trying to do computation during the query?
RavenDB doesn’t allow computation during the query, computation is only allowed during index. Consider moving the operation to an index.
Update: Actually, it works, just need to set a HandleNullPropagation option in Queryable attribute to false:
[Queryable(ResultLimit = 200, HandleNullPropagation = HandleNullPropagationOption.False)]
This is good news indeed.
OData support in MVC is still in Alpha stages, so.. be careful.
Logging is important, but wrapping every call in try/catch with log is.. annoying, so exception filter helps – this is the [ExceptionLoggerFilter] attribute I marked the controller with.
You can have a complete control over what you send to the user on exception, for example you can change the exception type sent, something like that:
if (context.Exception is NotImplementedException) context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
I was only interested in logging the exceptions, so I left it at that.
Btw, this filter will not intercept HttpResponseException, which is generally thrown by you, so if you need to log that – you’ll need to do that explicitly.
Product is validated using FluentValidation library. MVC’s attribute based validation is great.. until you need to put in some logic is there, or perform different validation in different method. In this case I wanted to make sure that when I’m creating a new object it doesn’t have an ID set, and when I’m updating – the ID is set.
Boom!
Links:
This solution on GitHub
OData support in ASP.NET Web API
OData: URI Conventions
Exception Handling in ASP.NET Web API