Starting the prototype : building the database

This week, I started working on a prototype of the UI for my event scheduler software to test if it makes sense on a tablet and on a desktop. Since this is a prototype, I’m not putting any effort in the architecture, error handling or on tricky edge cases and business logic for now. What I’m testing out exactly is :

  • Displaying an expanded and a collapsed list of sessions.
  • Showing an action menu to move the time of the session forward and backward (without saving it for now).
  • Navigating in the timeline to see the whole day.

I’m a beginner with the Entity Framework (EF), which is the object-relational mapping tool in ASP.NET: I never had to use a database in my projects since all the data was from web services. Still, I figured I could start the prototype by building a small data model, and use the scaffolding tool in Visual Studio to generate views. This way, I would have an almost free way to create and modify the data for sessions in my test. Also, this knowledge will come in handy later when I build the real thing. This was going to be a breeze…right?

Here is what I was aiming to do as seen in EF. In my model, I’m including only the event itself and sessions (talks) for the event. I’m supposing everything will be in the same room and on the same day for now. Even the event was not really needed, but I wanted to see how relations worked.
first database side project
Since I learned to work with databases the old school way by first building the database and then connecting to it with my application, I decided that I would create my database first and then generate the model classes from that database with Entity Framework. It seemed the most logical thing to do since I know exactly how I want things to be stored in the database. After a while though, I felt like I was going against the logical flow of things for EF by going database-first:

  • First, I’m used to having columns names and table names in lower case in my database, and objects names in CamelCase in the application, but EF uses the same names for both. Even when I renamed thing as I wanted them in the mapping, EF keep using the wrong case in SQL queries, so I couldn’t access any data.
  • Second, while Event and Session are great names to represent the concepts of an event to plan and of the sessions (talks) for the event, they are really dumb name to use in C# code. Those class names are already used in the .NET framework used to represent an event (handler) and a browser session. If I keep those names for my classes, I’ll have to use namespaces all the time which is a pain. And as seen with the first point, just renaming the classes and keeping this name in the database wouldn’t work either.
  • Third, EF plurializes everything by default, while I’m used to singular table names in my database. I found out about this when I tried to rename my tables SessionInfo and EventInfo in a last-ditch effort to solve the problem above: EF would plurizalize the table names to SessionInfoes and EventInfoes, messing the SQL queries to the database (again).

All those problems keep breaking the project, stopping my progress. Those are solvable for sure, but there is no point to putting up with that crap since there is a better way to do things. So, I decided to cut my looses, generate my database from my model classes and stop caring about the exact structure of the database for now.

As a bonus, going code-first doesn’t required messing with the designer as much: I can just use annotations on my model classes when I want to do something in particular, for example to specify which table names and column name to use. It’s also easier to manage in source control since the code, which is now the reference for the design of the database, can easily be checked in.
Class Diagram
Of course, this worked like a charm: I just created my classes from the generated code I already had from my previous tests, generated a database and scaffolding and everything worked on the first try. That will teach my to try and go against the standard for a framework…

Moving to code-first was not enough to fix my namespace problem of course, so I also renamed my classes ScheduledEvent and ScheduledSession. This name is even better than my first choice: when I’ll add features to publish schedules, I’ll probably need a pair of classes such as LiveEvent/LiveSession or PublishedEvent/PublishedSession anyway.

In summary, this part of the project didn’t go according to the plan to say the least. I now have a good headstart on how the model with work and on how to use Entity Framework so it was a good thing, but I didn’t want to spend this much time thinking about the model at this point just for a prototype. It’s not unexpected to have this kind of setback, there are still a lot of unknowns and there are sure to be more technical surprises lying around the corner.

Many Web.config have merged together

You can have more than one Web.config in an application and they will all be merged in the end, which is fine. Also, if you have a problem with the configuration for a given project it will usually show up in your development environment right away and will not make it to production.

But here is a problem that occurred to me a few times and that had me pretty stumped at first. When deploying an ASP.NET MVC or ASP.NET WebForms application to an IIS (Internet Information Service) server, it looked like configurations from unrelated Web.config or other .config files merged together. Errors were popping up from assembly versions or configurations that should not even be used in the new application! So what were those mystery configurations?

In IIS, the Sites folder is a container for all the applications and virtual directories of the server. The Sites folder has a physical root directory even it if doesn’t contain files specific to an application. In fact, configurations files from that folder are merged with the configuration of all your applications. Here is the configuration in IIS for the physical path of that folder:

DefaultWebSiteIn my case, the root folder pointed to another application on the same server, so the configurations made no sense for the new application. To solve the problem, I just made sure than the wwwroot folder was empty or contained only configurations that I intended to share with all the applications hosted on the server.

For references purpose, here is the configuration for the physical path of each individual application. You don’t need to point to a folder under wwwroot as long as the folder used has the proper permissions to be seen from the web.

HelloWorldApp

Character encoding with ASP.NET MVC helpers

In ASP.NET MVC, one of the ways to reuse parts of a web application template is to use helpers. There are two kind of helpers that can be used with Razor templates: helpers created directly from Razor templates using the @helper directive and helpers created from a C# class. To declare a helper with the @helper directive in a Razor view or in a .cshtml file in the App_code folder, you have to use the following syntax :

@helper PageHeader(string pageTitle)
   {
   <h1>@pageTitle</h1>
   }

Helpers created with the @helper directive always return a System.Web.WebPages.HelperResult that implements the System.Web.IHtmlString interface. This interface tells the Razor engine that the string returned is HTML-encoded and does not need to be encoded again to be safe. By default, all strings are encoded by the Razor engine, which means that characters not allowed in URLs or inside HTML tags are encoded into their character-entity equivalents : for example < and > becomes %3c and %3e.

But if you want to create your own helpers in a C# class, the return type to use is not that clear. The HelperResult class should not be used since it belongs the System.Web.WebPages namespace specific to the Razor syntax functionalities and not to the System.Web.Mvc namespace containing the ASP.NET MVC framework functionalities. The documentation of the HelperResult class also clearly indicates that it is not intended to be used directly from your own code. That leaves us with two options :

  • System.Web.HtmlString:  this class implements the IHtmlString interface and returns an HTML-encoded string that should not be encoded again. The only public method is the ToHtmlString method from the IHtmlString interface. The class is in the general System.Web namespace containing classes for the HTTP context.
  • System.Web.Mvc.Html.MvcHtmlString: this class extends the HtmlString class, so it also returns an HTML-encoded string that should not be encoded again. In addition to the ToHtmlString method, it aslo includes the factory method Create to create an MvcHtmlString from a text string and a IsNullOrEmpty method to check if the string is String.Empty, “” or null. The class is in the System.Web.Mvc.Html namespace containing classes that helps to render controls in an MVC application.

Since the MvcHtmlString class is specific to the MVC framework, I choose to use it for the helpers in my ASP.NET MVC projects. If new features are added for ASP.NET MVC, they will be available from that class and not from the less specific HtmlString class. Also, this is the class used by Microsoft for their own helpers, for example those the System.Web.Mvc.Html.InputExtensions class. I prefer to follow Microsoft’s conventions, which makes using their helpers into my own helpers easier. So, a good syntax for a helper built from C# code is :

public static class PageHelperExtensions
   {
   public static MvcHtmlString PageHeader(this HtmlHelper htmlHelper, string pageTitle)
      {
      // Create the HTML markup with TagBuilder or HtmlTextWriter

      return (MVCHtmlString.Create(tagBuilder.ToString()));
      }
   }

In conclusions, there are two other useful helpers to know about that deal with encoding :

  • @Html.Raw: Indicates to the Razor engine that a string is encoded and should not be encoded again. This can be used if you receive HTML markup from your model and want to make sure it is not encoded again.
  • @Html.Encode: Indicates to the Razor engine that a string should be encoded. This should not be used except in a few rare cases: since all strings are already encoded in Razor templates, this will double-encode the string.

Additional resources