Aurelia With Razor Views And NancyFx

Written on 06 July 2015

I've been toying these days with aurelia js trying to do some tutorials and understand how I can integrate it with my current NancyFx app (I'll have several aurelia apps each dealing with a certain aspect of my project). Each aurelia app has the sources (html views, razor view and view models written in typescript) in a directory where it makes sense (e.g: ~/Account/Settings) next to nancy modules, specific services etc (in case you're wondering, I'm using a business component based architecture where everything related to a component is in one directory, regardless of the technical aspects). The resulting static assets (js, maps, plain html) are copied to a /content/[app name] directory.

The Problem

Aurelia views are, by convention, in the same place and have the same name as the view model in my case, in the /content/[app] directory. Not really an issue, however I need some views to be generated i.e to be cshtml files which are found elsewhere. I can configure aurelia to look for views not ending in html, but I don't want every view to be a Razor file. Most of the views are plain html and only some of them need processing.

Basically, I need a way to use both simple html files and Razor views with minimal fuss.

Solution

After some thinking I came to the conclusion that it's better to implement everything server side. From aurelia's point of view every request is for a .html file. It's up to nancy detect which is which and to server either a static file or a processed razor view. By default, the /content directory is designated to contain only static assets so I needed a convention to filter the html files.

However, I need a way to mark that some html requests are for razor templates. Since every Razor view has a view model, I've decided to create an attribute which will mark a view model (and by convention the view) as an aurelia view.

  public class AureliaAppAttribute:Attribute
    {
        public string AppName { get; set; }

        public AureliaAppAttribute(string appName)
        {
            AppName = appName;
        }
    }

As I've said, I have more than one aurelia app, so each view model needs to declare to which app it belongs. For the ~/Account/settings app, any view model declared in that directory(and children of it) will be decorated with [AureliaApp("settings")].

Then I have an object which will recognize the aurelia view requests that are Razor views. I need that in order to filter the requests and allow the static html files to be served normally.

public class AureliaRouter
   {
       public static bool IsAureliaViewModel(Type t)
       {
           return t.HasAttribute<AureliaAppAttribute>();
       }

       public static string ContentDir = "/content";

       Dictionary<string,Func<object>> _handlers=new Dictionary<string, Func<object>>();


       public bool IsAureliaView(string path)
       {
           return _handlers.ContainsKey(path);
       }

       public object GetModel(string path)
       {
           return _handlers.GetValueOrDefault(path,()=>null)();

       }

       public void AddView(Type viewModel)
       {
           var appName = viewModel.GetAttributeValue<AureliaAppAttribute, string>(a => a.AppName);
           var url = ContentDir + "/" + ExtractViewPath(viewModel.Namespace, appName) + "/" +
                     viewModel.Name.RemoveLastChars(5).ToLower()+".html";
           _handlers.Add(url,viewModel.CreateInstance);
       }

       static string ExtractViewPath(string nspace,string appName)
       {
           var idx = nspace.IndexOf(appName);

           return nspace.Substring(idx,nspace.Length-idx).Replace('.', '/');
       }
   }

//search and register the view models
public static void RegisterAureliaViews()
       {
           typeof (RoutingUtils).Assembly.GetPublicTypes(AureliaRouter.IsAureliaViewModel)
               .ForEach(t=>_aurelia.AddView(t));
       }

This object simply computes the url that would match the razor view, based on a view model. So for a view found in ~/Account/Settings/foo/bar.cshtml it will generate the path /content/settings/foo/bar.html which is what aurelia will request. Once we have this we can filter the requests by setting our static content conventions in the nancy bootstrapper.

          nancyConventions.StaticContentsConventions.Clear();
           nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("content",null,"js","css",".map"));
           nancyConventions.StaticContentsConventions.Insert(0, (ctx, root) =>
           {
               var req = ctx.Request.Path;
               if (req.StartsWith("/content") && req.EndsWith("html"))
               {

                   if (RoutingUtils.Aurelia.IsAureliaView(req))
                   {
                       return null;
                   }
                   return new GenericFileResponse(req, ctx);
               }

               return null;

           });

Now, since I have no clue how I can return a razor View from the static content handler, I'll need a module which will handle the requests for the razor files. Here it is in all its glory.

public class AureliaViewsModule:NancyModule
    {
        public AureliaViewsModule()
        {
            Get[@"/content/^([a-z\.\/]*\.html)$"] = _ =>
                View[RoutingUtils.Aurelia.GetModel(Request.Path)];

        }
    }

And one more thing, all razor views need to to have an empty layout, we want the template only.

If you're using Asp.Net Mvc, the approach is very similar, you can filter and return a proper view/static template from an action filter.

Functional Programming Holy Wars

Written on 19 June 2015

These days functional programming seems to be the trend. And with the help of languages like F# , many programmers seem to embrace the functional paradigm. And these folks are very passionate about this, some of them on the verge to look like zealots which go on great length to convert the "unbelievers".

Personally, I use very little functional programming (FP), only when it appears as a "natural" solution i.e it makes sense for the problem I'm solving to express its solution as a pipeline of functions. I have a predominant object oriented mindset which fits me very well. This means I do prefer languages like C# and I have no interest in languages like F#.

It seems like FP looks like the new golden hammer for some developers, who now hails it as the best way to do everything. I disagree with this. It certainly fits some use cases, but in my case, it's just a tool I'm using very sparingly. And to be honest, I don't like the F# syntax so I won't be using it any time soon.

But not being a 'believer' seems to upset some people. They demand you to explain yourself and you better have a very good reason (read: one that they agree with) to reject the new tool. If you say to them that you've evaluated the paradigm/tool and it doesn't add much value for you, it's a sign you need more convincing. If you resists, you're just a close minded old dinosaur who doesn't want to be enlightened.

I think the cult-like mindset of some of the fans is harmful. I've noticed that developers are always looking for the next silver bullet, platinum hammer, the ultimate solution, recipe, mindset etc that will solve of our problems. And I know this will never happen. It's cool there is a new language enabling a non mainstream paradigm of doing things, but not everyone needs it and not everyone will like it. As long as a developer can build mainatainable solution in their language of choice, it's fine by me. Yes, even if that language is javascript, ruby or php. In the end, they're all tools and we should be more concerned about the quality of the result and less about using a specific tool.

As a funny note, I am a big fan of DDD. I consider that it should be used for every project, as a strategic tool, of course. Personally, I'm using it this way even if lately I find myself writing a lot of CRUD stuff. But I've used the DDD mindset to reach the conclusion that in the end I'm dealing with many CRUD use cases. Some people said DDD is OOP done right and I agree with them. It fits my mindset naturally. But DDD can be implemented in a functional way too and some devs are using it this way.

In conclusion, I and other developers will continue to use our OOP mindset and languages because it makes the most sens to us. Other devs will use functional programming. I don't think it should be a 'war' about which is better and which is the one true way. I agree with FP fans that FP is not very well known and it will benefit programmers (at least some of them) to be aware of it.

If you have an opinion about why FP is great or why it sucks feel free to send me a PR.

How To Use Razor with NancyFx

Written on 16 June 2015

After using Nancy to build an Api app, I've decided to give it a try and use it instead of Asp.Net Mvc. I was a bit weary because I knew things are not that straightforward when it comes to Razor. Turns out I was partially right.

But first things first. The docs do a pretty good job explaining how to configure Razor, however there are some gotchas.

  1. Every bit of code you'll use in a razor view if it happens to be in a different assembly than the view, needs to be manually referenced, regardless if the current assembly reference it and your view has the required using statement. Coming from Asp.net Mvc you might be tempted to configure razor in app/web.config. Personally, I find it easier to use the programmatic option, that is implementing IRazorConfig. Now, everytime you need an assembly referenced in a Razor view just add it to that class.

Here's an example

 public class RazorConfig : IRazorConfiguration
   {
       public IEnumerable<string> GetAssemblyNames()
       {
           yield return "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
           yield return "Common";

           yield return "HtmlTags";

       }

       public IEnumerable<string> GetDefaultNamespaces()
       {
        //contains html extensions
        yield return "Web._Auxilia.Html";

       }

       public bool AutoIncludeModelNamespace
       {
           get { return true; }
       }
   }

While my webapp references System.Web and other assemblies, I still need to include it here for Razor to know about it. And this needs to be done when refactoring moves some code (used by the view) from one assembly to another or one namespace to another.

  1. All of your views need the @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<My_Model> with full path for the view base, instead of @model MyModel . This is easily solvable with a file template (at least if using Resharper).

  2. When defining a view convention the path should not start with '/' .

View Conventions

And speaking of view conventions, this is a very nice part of Nancy (you can get a similar feature in Asp.Net Mvc using my MvcPowerTools library) that allows you to configure the view path you want. This means that you can put your some of your views in a View directory, others in next to the Nancy module or the view model itself. All these with just a couple lines of code.

Here's an example

 //in my nancy bootstrapper
protected override void ConfigureConventions(NancyConventions nancyConventions)
       {
           ConfigureViews(nancyConventions);
       }

       private static void ConfigureViews(NancyConventions nancyConventions)
       {
           nancyConventions.ViewLocationConventions.Clear();
        nancyConventions.ViewLocationConventions.Insert(0, (view, model, ctx) => "{1}/{0}".ToFormat(view, ctx.ModulePath));
           nancyConventions.ViewLocationConventions.Add((view, model, ctx) =>
           {
               var tp=(model.GetType() as Type);
               var asm=tp.Assembly.GetName().Name;
               var path = tp.Namespace.Substring(asm.Length+1).Replace('.','/');

               //path is model namespace without the assembly name
               return "{0}/{1}".ToFormat(path,view);
           });

           nancyConventions.ViewLocationConventions.Add((view, model, ctx) => "common/{0}".ToFormat(view));
       }

Since I don't want to use any existing conventions, I clear the list and define my own. The first convention tells the engine to look for the view in a directory that has the same name as the module path. This usually happens if the module is used to define an equivalent to a asp.net mvc area. And usually, the module itself is in a directory with that name.

The next convention is the most interesting one. It's for views sitting next to their view model. While in asp.net mvc returning a View(model) meant the view name is the action name found in a controller (or Shared) directory, in Nancy return View[model] looks for a view with the model type name (but without the "Model" suffix). And this might be strange but it's actually a great feature: just look at the view/model name and you already know the model/view name ;) . Also this means you should use one view model per view. And as a tip, always define a view model even if you plan to reuse an existing data structure. It's a very small price to pay for maintainability.

As you can see there's no view extension mentioned. That's because the view locator searches for all files with that name regardless of their extensions and then uses the found extension to identify the view engine. This way, switching for Razor to Spark (for example) means you just have to install the Spark view engine and your code stays untouched.

Html Tags and Helpers

In this regard, you don't have much. While there is a nuget bringing the asp.net mvc html helpers to Nancy, it's pre release and it's a port. This is not wrong, but I do prefer a more fluent (read: not ugly) way of doing things. Besides writing the html code directly , which I don't recommend as a general thumb rule, you can use the HtmlTags library to define your own Html Helpers for Nancy. It's more work but it's trivial and you get some cool benefits.

Here's an example of a 'register user' form

 <form action="/register" method="POST">

    @Html.HiddenTag(d=>d.OperationId).Raw()
    <div class="form-group">

        @Html.Label(d=>d.Fullname).Raw()
        @Html.Textbox(d=>d.Fullname).AddClass("form-control").Raw()
        @Html.ValidationText(d=>d.Fullname).Raw()

    </div>
    <div class="form-group">

        @Html.Label(d=>d.Email).Raw()
        @Html.Textbox(d=>d.Email).Raw()
        @Html.ValidationText(d=>d.Email).Raw()

    </div>
    @Html.FormField(d=>d.Password,()=>Html.Textbox(d=>d.Password).PasswordMode())

    <div class="form-group">
        <input type="checkbox" name="RememberMe" value="true"/><label>Remember Me</label>
    </div>

    <button type="submit">Go</button>

 </form>

All the helpers are defined by me, they just provide a simple way to use HtmlTags in a Razor view. Here's a small excerpt

      public static TextboxTag Textbox<T>(this HtmlHelpers<T> html,Expression<Func<T,object>> valueSelector)
       {
           var name = valueSelector.GetName();
           return html.Textbox(name);
       }

      public static TextboxTag Textbox<T>(this HtmlHelpers<T> html, string name)
      {
          var val = html.Model.GetPropertyValue(name) ?? "";
          return new TextboxTag(name, val.ToString()).IdFromName();
      }

       public static HiddenTag HiddenTag<T>(this HtmlHelpers<T> html, Expression<Func<T, object>> valueSelector)
       {
           var name = valueSelector.GetName();
           var result= new HiddenTag();
           result.Name(name).IdFromName();
           return result;
       }

      public static IHtmlString FormField<T>(this HtmlHelpers<T> html, Expression<Func<T, object>> valueSelector,
           Func<HtmlTag> factory = null)
       {
           if (factory == null)
           {
               factory = () => html.Textbox(valueSelector);
           }
           var result = new DivTag().AddClass("form-group");
           result
               .Append(html.Label(valueSelector))
               .Append(factory())
               .Append(html.ValidationText(valueSelector));
           return result.Raw();
       }

       public static HtmlTag ValidationText<T>(this HtmlHelpers<T> html, Expression<Func<T, object>> valueSelector)
       {
           var name = valueSelector.GetName();
           return html.ValidationText(name);
       }
       public static HtmlTag ValidationText<T>(this HtmlHelpers<T> html, string name)
       {
           var result = html.RenderContext.Context.ModelValidationResult;
           if (result.IsValid) return HtmlTag.Empty();
           var error = result.Errors.GetValueOrDefault(name, new ModelValidationError[0]).FirstOrDefault();
           if (error==null) return HtmlTag.Empty();
           var tag=new SpanTag();
           tag.Text(error.ErrorMessage);
           return tag.AddClass("error");
       }

       public static IHtmlString Raw(this HtmlTag tag)
        {
            return new NonEncodedHtmlString(tag.ToString());
        }

Some interesting things:

  • All (almost) helpers return a HtmlTag object or a type inheriting HtmlTag
  • Because Razor html encodes everything, we need to tell it to not encode the tag, hence the Raw() extension method
  • Validation result object (created by a call to Validate or BindAndValidate in a Nancy module) can be found at [html helper].RenderContext.Context.ModelValidationResult . That's where the ValidationText takes the errors messages from.

Creating your own helpers means it's easier to add changes later. For example, I can decide to create a helper AsSubmit() for a button or link tag, which can add or remove a specific css class or attribute or include directly a css class for a specific tag (such as "form-control" for textboxes). HtmlTags library has some support for defining your own html conventions (that can manipulate tag generation based on model) but the docs are lacking in this regard, AFAIK is still work in progress.

Conclusion

Clearly, using Razor with Nancy is not as smooth as with Asp.Net Mvc, but for me it's not a big deal. I like Nancy as a framework and the 'price' for using razor is quite small once you have a workflow defined. Actually, I'd say it's easier for a asp.net veteran to write a maintainable app with Nancy, while it's easier for a beginner to use Asp.Net Mvc. You can do everything with both, but with Nancy you are more in control.

DDD Concepts As One Liners

Written on 25 May 2015

Bounded Context : all models sharing the same domain language

Aggregate:

  • a group of objects that need to be consistent together in order to represent a valid domain concept
  • a consistency boundary around a domain concept, often represented as an object graph (from Mathias)

Aggregate Root: the object from the Aggregate that enforces the aggregate's consistency and acts as its 'representative'

Entity: a business object representing a domain concept with a stable identity throughout changes over time

Value Object: an immutable object representing a (composite) value that has domain significance

Domain Service: implements a domain use case and/or provides domain utilities

Application Service: acts as an adapter between the app's clients and the domain

Domain Event: a data structure representing one domain change

Repository : the object responsible for persisting/loading aggregates

Criteria: it tells the Repository what kind of aggregates to retrieve

Specification: an implemention of a business rule aspect

Eventual Consistency: an use case involving multiple aggregates modifies (and persists) one aggregate at the time, but not in an atomic fashion

Unit of Work: basically, an anti pattern

CQRS: have one model (behaviour and data) handling business state changes and at least one other model handling non-domain queries

Event Sourcing: express a business object state as a stream of events

Want to contribute? Send me a PR

DDD - Identifying Bounded Contexts and Aggregates, Entities and Value Objects

Written on 31 October 2014

Let me be clear about one thing concerning Domain objects: they aren't either Entities or Value Objects (VO). You can have simple objects in your Domain and you can have objects which have a business meaning. Only an object representing a Domain concept can be classified as an Entity (it has an id) or a VO (it encapsulates a simple or composite value).

Bounded Context (BC)

First thing before starting an app is to identify the Bounded Contexts. Luckily this is quite simple. First of all let's remember that a BC simply defines a model that is valid (makes sense) only in that BC. If you're designing your app as a group of autonomous components (and you should) aka vertical slices aka microservices (for distributed apps) working together, then each component is a BC. For example, I'm working on a Saas app and these are some of the components: Membership, Subscription, Invoicing, Api Server, Api Processor. Each is like a mini app in itself, each has their own domain and thus their own model which makes sense only for that component (BC).

The components being autonomous, they don't depend one on another (at most they know about other's abstractions) so they don't share the model i.e the model of one BC doesn't cross its boundaries to be available in other BC. But, a subscription is related to an account so it might seem that Subscription must know about Membership model. Similarly, Invoicing is related to an account and needs data usually found in Subscription. How do we solve this, without coupling the components (breaking the boundaries)?

Each BC has its very own definitions of concepts even id it happens that they share the same name. An Account is a fully defined concept in Membership but it's just an id in Subscription, Invoicing or any other BC and that's because the BC itself controls the definition. So the Account is not just an id because the Membership Account entity has a property Id, but because the other component said so. However, in practice, a concept which is an entity in other BC will at least be defined as an id in other BCs. But the VO are a different story and each BC really has their own definitions. Of course, some concepts may be generic enough that their definitions will be identical. But that's just a coincidence, and in fairness, if a BC shares a lot of concept and definitions with another, perhaps they should be merged.

What about the data that a BC might need from another? A BC should be like a black box. You don't see what's inside, you know only about input and output. In a message driven app, this means you send commands to be handled and you get events. Those are DTOs and contain all the relevant (in/out)data for an use case. So we have our BC listening to other BC's events. If you really want to keep things decoupled, because you want a reusable component, then you can use a mediator that will listen to one BC then send the relevant data to the other one. That's the approach I've taken with the Invoicing component (so that it wouldn't know about anything Subscription).

So, a BC takes DTOs or commands as input then publishes events as output. A BC model exists only in that BC and all the DTOs are just flatten aspects of that model. Since an event is just a data structure with no business rules attached (consider it a read model ;) ) that data can travel to any other BC that can extract the relevant information from it. In the end, BCs 'communicate' via simple data that only have the role of input/output.

Aggregates

Identifying Aggregates is pretty hard. An aggregate is a group of objects that must be consistent together. But you can't just pick some objects and say: this is an aggregate. You start with modelling a Domain concept. For a non trivial concept, you end up with at least 1 entity and some VO. Regardless of how many entities, VOs or simple objects will be involved, the important things are that you'll have a 'primary' entity (named after the concept) and other objects that work together to implement the concept and its required behaviour. Those together form an Aggregate and the 'primary' entity is the Aggregate Root (AR).

The purpose of an AR is to ensure the consistency of the aggregate, that's why you should make changes to one only via the AR. If you change an object independently, the AR can't ensure the concept (the aggregate) is in valid state, it's like a car with a loose wheel.

Before rushing out to name any entity an AR, first make sure you know the aggregate then make sure the AR really is responsible for the aggregate consistency. An entity acting as a container for other objects is not an AR. The consistency part makes it an AR.

Domain Entity

Modelling a Domain concept is more than coming up with a name and some properties. You have the name 'Foo' then what? If you start thinking about its properties or behaviour you'll end up with a data structure (resembling a table schema) with functions. That's because we think about all things that we want to persist and not about how the concept is defined and used by the Domain. We want to come up with a model fit for everything and that's the wrong approach.

In order to define Foo you start with the use cases of Foo, better yet, implement those use cases as tests. This is how you identify the relevant properties and behaviour, that's how you design the entity. Once you have the interface defined, you can go wild with the implementation. In practice, you'll notice how you start with one entity and you end up with a whole aggregate. And that's how it should be, anyway.