Avoiding monolithic applications

I spend a lot (perhaps too much?) time worrying about how applications can become too big and extend beyond their original scope. When asked to create a small application that is either stand-alone or only slightly linked to other systems, it’s too tempting to just add it as an exatra section of an existing application, rather copy/re-create the infrastructure needed for it to be in its own application. Visual Studio now provides a lot of the infrastructure, so with a few button clicks you can have an ASP.Net MVC application that’s all plumbed together but often the first thing you do is get rid of the that auto-generated stuff and it doesn’t include all of your own standard customisations. There are a few ways to implement those standard customisations: ...

April 10, 2015 · 3 min

JWT and CORS for cross-site API authentication

In my previous post on avoiding monolithic applications, I mentioned that JSON Web Tokens and CORS could be used to access protected web apis on other sites. Here’s the why and how. The requirement for accessing protected web apis on other sites Ideally (my ideal), each application that is developed would be relatively compact and include only the functionality that is unique to that application. Functionality from other applications would be provided by APIs in those applications and generic functionality (e.g. a staff lookup) would be provided by an application (or multiple) that all other applications can access (almost like a CDN for functionality). ...

April 10, 2015 · 5 min

Updated error handling

In Managing Errors in MVC I got close to having record level error handling working as I wanted but I had to create a view for each error when usually the error is a single line of text that could be stored in a config file. Based on my original code and http://weblogs.asp.net/gunnarpeipman/asp-net-mvc-3-creating-httpstatuscoderesult-with-view-based-body Helpers\ExceptionHelper.cs using System; using System.Linq.Expressions; using System.Net; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Collections; using System.Collections.Generic; namespace MyProject { public class ExceptionHelper : ViewResult { private ExceptionName \_exceptionName; private HttpStatusCode? \_statusCode; private bool? \_logException; public ExceptionHelper(ExceptionName exceptionName, HttpStatusCode? statusCode = null, bool? logException = null) { \_exceptionName = exceptionName; \_statusCode = statusCode; \_logException = logException; } public override void ExecuteResult(ControllerContext context) { HttpStatusCode returnStatusCode = HttpStatusCode.BadRequest; bool returnLogException = true; string ExceptionDescription = string.Empty; string sViewName = "Exceptions/\_GenericException"; var httpContext = context.HttpContext; var response = httpContext.Response; // get the defaults for this exception ExceptionActions theseExceptionActions; if (ExceptionDefaults.TryGetValue(\_exceptionName, out theseExceptionActions)) { if (theseExceptionActions.UseCustomView) { sViewName = "Exceptions/" + \_exceptionName.ToString(); } ExceptionDescription = theseExceptionActions.ExceptionDescription; if (null == \_statusCode) { returnStatusCode = theseExceptionActions.StatusCode; } else { returnStatusCode = (HttpStatusCode)\_statusCode; } if (null == \_logException) { returnLogException = theseExceptionActions.LogException; } else { returnLogException = (bool)\_logException; } } response.StatusCode = (int)returnStatusCode; response.StatusDescription = ExceptionDescription; ViewBag.ExceptionDescription = ExceptionDescription; ViewName = sViewName; if (returnLogException) { // log the exception Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception(\_exceptionName.ToString())); } base.ExecuteResult(context); } public enum ExceptionName { DataNotValid, NoPermissionToManageThisPerson, NoPermissionToManageThisProject, RecordNotFound, RecordNotSpecified }; /// <summary> /// Most exceptions will have UseCustomView=false, so the ExceptionDescription will be used for the error message that is displayed in the \_GenericException view /// If a custom view is required, it will have the name of the exception /// </summary> public struct ExceptionActions { public bool UseCustomView; public HttpStatusCode StatusCode; public bool LogException; public string ExceptionDescription; } public static Dictionary<ExceptionName, ExceptionActions\> ExceptionDefaults = new Dictionary<ExceptionName, ExceptionActions\>() { {ExceptionName.DataNotValid, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.BadRequest, LogException = true, ExceptionDescription = "Data provided was not valid"}}, {ExceptionName.NoPermissionToManageThisPerson, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.Forbidden, LogException = false, ExceptionDescription = "You don't have permission to manage this person"}}, {ExceptionName.NoPermissionToManageThisProject, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.Forbidden, LogException = false, ExceptionDescription = "You don't have permission to manage this project"}}, {ExceptionName.RecordNotFound, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.NotFound, LogException = false, ExceptionDescription = "Record was not found"}}, {ExceptionName.RecordNotSpecified, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.BadRequest, LogException = false, ExceptionDescription = "Record not specified - one or more identifiers were missing"}}, }; } } Views\Shared\Exceptions\_GenericException.cshtml ...

February 10, 2015 · 3 min

Getting a WebApi2 controller to return HttpStatusCode.Forbidden

If your WebApi controller is checking that the user has permission to view a particular record and it turns out that they don’t then you will want to return a status of Forbidden, rather than Unauthorized as discussed here: http://stackoverflow.com/questions/238437/why-does-authorizeattribute-redirect-to-the-login-page-for-authentication-and-au/5844884#5844884 (You might also want to override the AuthorizeAttribute class as described there) WebApi2 controllers now return IHttpActionResult rather than HttpResponseMessage (see http://stackoverflow.com/questions/21758615/why-should-i-use-ihttpactionresult-instead-of-httpresponsemessage). It’s easy to return a result from the System.Web.Http.Results Namespace e.g. return Unauthorized(); But the namespace doesn’t contain Forbidden, so instead use: ...

January 14, 2015 · 1 min

Managing errors in MVC

Error logging Elmah seems to be the most popular tool for error logging but the Elmah website doesn’t have much up to date information on how to get started. To get Elmah installed, secured and logging to somewhere more permanent than keeping the log in-memory, follow this guide: http://www.erikojebo.se/Code/Details/607 Error handling Elmah just logs error, it doesn’t help the user. So you also need to handle the errors, which this article covers nicely: https://www.simple-talk.com/dotnet/asp.net/handling-errors-effectively-in-asp.net-mvc/ ...

January 14, 2015 · 4 min

ASP.Net MVC and URLs ending in a decimal or float

In your MVC site, you might want this URL to purchase 2.5 kilos of cheese for you https://www.mysite.com/cheese/purchase/2.5 Unfortunately it won’t be recognised as a route to the purchase method within the cheese controller. The good news is that this will work: https://www.mysite.com/cheese/purchase/2.5/ Note the extra slash at the end This is an explanation why: http://stackoverflow.com/questions/21387974/why-is-my-web-api-method-with-double-args-not-getting-called It’s fairly unusual to have a valid reason for a URL like this. If you want to pass a parameter that’s a float, it’s more likely that you would want to post the data.

November 14, 2014 · 1 min

EntityFramework Reverse POCO Generator and Views

EntityFramework’s own tool to generate a model from a database is slow and buggy. It’s particularly a problem if you update your database (change table names, field names etc.). EntityFramework Reverse POCO Generator is a great, lightweight replacement – it’s fast, configurable and just works. Also, the entities created can be the same as those created by the built in tool, so it is possible to switch to it part way through developing a project. ...

September 20, 2014 · 1 min

Casting one list to another with Omu.ValueInjecter

Omu.ValueInjecter is great for quickly casting one entity to another, especially when the property names match up, as there’s no configuration to do. This is really handy if you have a view model that’s just a cut down version of your model and you want to get the data from the model into the view model. If you’ve got a list of model entities that you want to cast to a list of view model entitites, you can do so without looping through them: ...

August 11, 2014 · 1 min

Steps in creating a new MVC application

Create the database Create the project/solution in Visual Studio don’t give the project the same name (in the same case) as one of the tables or the compiler will become confused between types and namespaces choose MVC and optionally Web API and unit tests leave authentication as Individual User Accounts Create an application in IIS that points to the project Change the Web properties for the project to use Local IIS ...

March 24, 2014 · 2 min

Changing the templates used to generate MVC views

If you use Visual Studio to generate MVC views, it will use T4 templates. This is how to edit those templates. Go to: C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcView Make a backup copy of the folder (don’t put the backup inside the folder or VS will complain that it has multiple templates to choose from) Then, open all of the files (or at least all of the *.cs.t4) files) in a text editor. ...

March 21, 2014 · 1 min