Generics Primer – Part 1

When generics were first released, the generic collections where the first place that I used them. They removed a lot of the boilerplate code when it came to creating strongly typed collections. In 1.x you would inherit from the base class of the type of collection you wanted, and then implement strongly typed versions of methods such as Add, Remove, Contains. An example of this can be found here. Thanks to generics you don’t need to create a MyClass1List and a MyClass2List you can simply instantiate a new List<MyClass1>() and new List<MyClass2> without needing to write the plumbing code to have this work.

When .Net 3.5 was released it included one of my favorite features in .Net, LINQ which is a set of extension methods that make extensive use of generics, allowing for removal of much of the boilerplate involved with searching collections.

In my next post I will talk about creating some simple generic classes and methods.

Getting imports working with dotless and CssBundles

I was watching Single Page Apps with HTML5, Web API, Knockout and jQuery by John Papa on pluralsight and one of the pieces was sending compiled less files down using the bundling.

Unfortunately this did not work while using @import because the current directory was set to my IIS Express directory. After searching most suggestions were to use Directory.SetCurrentDirectory but didn’t really like that solution so this is what I decided on:

DotNetOpenAuth with AppDirectory removed

In my previous post I had talked about my decision to implement OpenId, and how DotNetOpenAuth worked well for this. In this post I will talk a little about the only issue that I ran into while doing this.

The root of this issue had to do with how my hosting is setup for sites that have low traffic. I host these sites on winhost which allows for an unlimited number of domain pointers. They also have the URL Rewrite module, so I can rewrite http://webquestbuilder.com/ to http://webquestbuilder.com/sitedir enabling the site to be moved later when demand requires more horsepower without having to deal with the removal of the sub directory.

The problem that came from this setup was that DotNetOpenAuth determined that the releam was webquestbuilder.com/sitedir instead of webquestbuilder.com, and returned from openid with to the sitedir/authenticate.  Andrew Arnott pointed me in the right direction pretty quick after my tweet. Here is what I ended up with to fix this, it is in 2 parts.

The first is making the request:

if (isInSubDir)
{
request = openid.CreateRequest(Request.Form["openid_identifier"], new Realm("http://webquestbuilder.com/"),
new Uri("http://webquestbuilder.com/User/Authenticate/"));
}
else
{
request = openid.CreateRequest(Request.Form["openid_identifier"]);
}

The second part is dealing with the response:

var isInSubDir = Request.ApplicationPath!="/";
IAuthenticationResponse response;
if (isInSubDir)
{
var absoluteUri = httpRequest.Url.AbsoluteUri;
var rawUrl = httpRequest.RawUrl;
if(isInSubDir)
{
absoluteUri = absoluteUri.Replace(Request.ApplicationPath, "");
rawUrl = rawUrl.Replace(Request.ApplicationPath, "");
}
var httpRequestInfo = new HttpRequestInfo(httpRequest.HttpMethod, new Uri(absoluteUri), rawUrl, headers, httpRequest.InputStream);
response = openid.GetResponse(httpRequestInfo); �
}
else
{
response = openid.GetResponse();
}

Open Id with DotNetOpenId

I recently integrated OpenId into a project that I am working on with my wife, WebQuest Builder in order to avoid the extra considerations related to storing user password.

Originally I had planned on using RPXNow in order to do this. But after reading about how realms worked, specifically that  Google gives a different identifier for each realm, I decided against this option. Because

while RPXNow does have support  for custom realms, webquestbuilder.com instead of webquestbuilder.rpxnow.com, it would cost $99/month in order to get this. And after my wife made a comment that it seemed almost like someone phishing for her account do to the webquestbuilder.rxpnow.com in Googles OpenId form.

The other option that I had been considering had been DotNetOpenAuth which was very simple to integrate. It took about an hour to get it running in my development environment. I only had one issue when I pushed it live, which I will go into in a future post. For the OpenId selector I used Jarrett Vance’s Id selector for the Sign In.

After showing it to a few people I ended up making a few tweaks to the Id Selector. The first  chance that I made was to change it so that the OpenId checkbox did not show up, because a couple of the people I showed it to tried entering in their gmail address instead of Google’s OpenId Url. The other change I did was order them by which providers I thought they were most likely to be using, I hope the Microsoft gets their OpenId provider going soon so that I can integrate hotmail/live accounts into this.

ScriptControl question

As of late I have gotten a chance to use the ASP.Net AJAX extenders and script controls, and so far am really liking how they work, though it would be nice if adding the .js was a little cleaner then manually adding them to the assembly wether in the AssemblyInfo.cs or the controls cs file.

I have to say I really like the extender and script controls that come with the ASP.NET AJAX. They really are so much nicer to work with then building up Javascript strings in the CS file of the server control.

I do have a question about them though. One of the ScriptControls I made uses a webservice to pull data if the service name is set. At the moment I have it dynamically registering an JSON script service based webservice. Unfortunately I have found that this is not an optimal solution since the name of the Javascript object created by the ScriptService changes depending on the namespace and class name of the service.

I am sure that there is a better way to do this, but I am not exactly certain of it. Any suggestions or links would be appreciated.

Lazy list

I have been following Rob Conery’s posts on the MVC Storefront, and trying the repository/pipes-filters for data access that he has been using.

While trying out the implementation of a LazyList he was using, I had noticed that the example table was being joined onto the category table. At the time however, I really had not thought much of it, until I read MVC Storefront: Brainbender Intermission which got me thinking.

Admittedly, I don’t really have to much of a problem with it loading all of the examples for all the categories at one time at the moment. However, I figured it would be nice to have it work the way intended, and query the database for the examples in a category only when asked for.

I liked the idea of the LazyList, and since I was already using a Service class for all data access, along with setting up the category hierarchy I moved the creation of the LazyList of examples property into the the GetCategories method of the service class.

It seems that as long as the LazyList is created after the categories .ToList() call it properly works. So I ended up with this code:

            categories.ForEach(category =>
            {
                category.Examples =
                    new LazyList
                        <DevExamples.Data.Example>(
                        from e in repository.GetExamples()
                        where e.CategoryId == category.ID
                        select e);

                var subCategories = (from sub in categories
                                     where sub.ParentId == category.ID
                                     select sub).ToList();
                category.SubCategories = subCategories;

                subCategories.ForEach(c => c.Parent = category);

            });

 

Technorati Tags:

Login via Usercontrol View + jQuery

Since administration was the next part I wanted to work on.

I decided that for the moment I just want a little login for in the upper corner

I decided to put the login screen view logic into a user control, and added the following user control named Login.ascx and placed it into the Shared

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<%if(!Page.User.Identity.IsAuthenticated) {%>
    <form action="/Home/Login" method="post" id="LoginForm">
        <span id="EmailLabel">Username:</span><br />
        <%=Html.TextBox("Username")%><br />
        <span id="PasswordLabel">Password:</span><br />
        <%=Html.Password("Password")%><br />
         <span id="Error">
            <%=ViewData.ContainsDataItem("Message") ? ViewData["Message"] + 
               "<BR />" : ""%>
        </span>
        <%=Html.SubmitButton("Submit", "Login")%>
    </form>
<%}else {%>
        <span>Not <%=Page.User.Identity.Name %><br />    
        <%=Html.ActionLink<DevExamples.Controllers.HomeController>(c => c.Logout()
            , "Logout", new { id = "LogoutLink" })%></span>

<%} %>

 

And added the user control to the masterpage using

<div id="Login"><%=Html.RenderUserControl("~/Views/Shared/Login.ascx") %><div>

 

I was going to use

using (Html.Form<DevExamples.Controllers.HomeController>(c=>c.Login()
   ,System.Web.Mvc.FormExtensions.FormMethod.post,new {id="LoginForm"}))

 

to create the form (because it is a lot cooler), but couldn’t get the html attributes to work and was more interested in getting the dynamic stuff working then looking at the code for the extension method in the MVCToolKit, in other words being lazy.

 

I thought about putting the authentication checking logic into the controller. But handling it this way made it a bit simpler, and more self contained, so until I find a compelling enough reason I will be leaving it this way.

After I had the user control showing up, I decided to hook up the actual authentication. I decided to go with forms authentication, and set it up using the button in the solution explorer.

Next it was time to create the login and logout controller actions, which I decided would best fit in the HomeController, At first I had thought to create two separate views, one for when logged in and one for logged out, then remembered Phil Haack, at least I think it was him, something about being able to use user controls in the RenderView method of the controller.

I ended up with the following two controller actions:

[ControllerAction]
public void Login()
{
    if (!ControllerContext.HttpContext.User.Identity.IsAuthenticated)
    {
        if (Request.RequestType == "POST")
        {
            string userName = Request.Form["Username"];
            string password = Request.Form["Password"];

            if (Membership.ValidateUser(userName, password))
            {
                FormsAuthentication.SetAuthCookie(userName, true);
                //Set cookie and redirect
                RedirectToAction("Login");
            }
            else
            {
                ViewData.Add("Message", "Invalid Username/Password");
            }
        }
    }
    RenderView("Login");
}
[ControllerAction]
public void Logout()
{
    FormsAuthentication.SignOut();
    RedirectToAction("Login");
}

 

Since it was allowing me to just render out the user control, I decided there was no point to refreshing the whole page, so decided to use a AJAXish way of doing it. So I decided it was time to pick a javascript library. And since Phil had provided a link to  Using script.aculo.us with ASP.NET MVC by Chad Myers,I decided to go with jQuery for this (that and it seemed to fit better).

After a bit of reading through their tutorials I added this to the header section of the master page.

<script src="../../Content/jquery.js" type="text/javascript"></script>
<script src="../../Content/jquery.form.js" type="text/javascript"></script>
<script type="text/javascript">
    var readyFuncs = function() { 
        $('#LoginForm').ajaxForm(function(result) { 
            $('#Login').html(result); 
            $(document).ready(readyFuncs); 
        }); 
        $('#LogoutLink').click(function(){
            $.get('/Home/Logout',function(result){
                $('#Login').html(result);
                $(document).ready(readyFuncs); 
            });
            return false;
        });
    };
    $(document).ready(readyFuncs);
</script>

The only real snag I had run into with this was that each time the Login div was refreshed I had to reregister the events.

Got my nice Urls working

Its amazing how fast things can be done when not fighting bad assumptions. In this case it was that my admin URLs needed to use the nice descriptive URLs, instead of just /[Controller]/[Action]/[id] type routing.

Once I realized I was making things overly complicated I, I ended up with a set of routing functions that are actually a bit less complicated then what I would have come up with if I had been able to extend the RouteTable the way I had planned originally.

I also decided that I didn’t like the idea of having the make every category and example name unique. Most of this was that I’m not the creative, but I also realized that it would be really ugly I wanted to have namespaces as categories. For example, it would not have been possible to have both C/System/Windows/Forms/Control and C/System/Web/UI/Control since Control would have had to be unique.

I also decided that I was going to set a limit to the depth of categories that the site was going to have, though it is easy to update this. First I made a function that would generate routes similar to those previously posted.

protected void CreateRouteSet(string baseRoute, string baseName
    , int maxDepth, object Defaults)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < maxDepth; i++)
    {
        if (sb.Length > 0)
            sb.Append("/");

        sb.AppendFormat("[{0}{1}]", baseName, i);

        RouteTable.Routes.Add(new Route{
         
            Url = String.Format(baseRoute,sb.ToString()),
            Defaults = Defaults,
            RouteHandler = typeof(MvcRouteHandler)
        });
    }
}

protected void Application_Start(object sender, EventArgs e)
{

    CreateRouteSet("C/{0}", "Category", 6,
        new { Action = "Index", Controller = "Categories" }
        );

    //Other routes using the standard [Controller]/[Action]/[Id]

}

This will setup routes to handle category hierarchies up to 6 deep.  And add Category1,Category2… into the RouteData.Values collection in the controller.

Next I set up the code to allow me to handle the route, which I did in the model, adding a method that takes an IDictionary<string,object>.

public Category GetCategoryFromRouteData(IDictionary<String,object> data)
{
    //Grab just the category data
var navList = from route in data where route.Key.IndexOf("Category") == 0 orderby route.Key select new{Key = route.Key, Value = route.Value.ToString()}; string sqlSelect = @" SELECT {0}.* FROM Category {0} {1} WHERE {0}.Name = {{0}}";
//{{{2}}} will be replaced with {{<param index>}}
string join = @"INNER JOIN Category {0} ON {0}.[Key] = {1}.ParentKey AND {0}.[Name] = {{{2}}} //This is the name of the category I am actually interested in
var mainCat = navList.Last(); //Build a list of category values to for parameterized query
List<string> values = new List<string>(); values.Add(mainCat.Value); StringBuilder sb = new StringBuilder(); string lastCategory = mainCat.Key; int i = 1; foreach (var item in navList.Reverse().Skip(1)) { sb.AppendFormat(join, item.Key, lastCategory,i++); values.Add(item.Value); lastCategory = item.Key; } string sql = String.Format(sqlSelect,mainCat.Key, sb.ToString()); Category cat = this.ExecuteQuery<Category>(sql, values.ToArray()).Single();


//GetDisplayCategory skips over categories that have only 1 subcategory
//and no examples, allowing me to have the planned Url structure without
//
requiring the user to navigate through several empty categories.
return GetDisplayCategory(cat); }

I had planned on having doing it all LINQ to SQL expressions, but it was taking more time then it was worth to figure out how to do the hierarchy lookup from the category names.  I need to add some caching of the key lookups at some point, since the joins look like they might get a bit nasty for deep categories, but that can wait.

I added a few overloads to the HtmlHelper ActionLink extension methods to handle making the nice Url links.

Now I need to figure out how to deploy the usercontrols that will contain the executable part of the example. I have had some problems with compilation sometimes when I had the website directly upload the usercontrols. Plus I would like them to go into source control when I add them.

Technorati Tags:

Initial thoughts on Microsoft MVC

My first thought is, I really wish I could use this at work, but it is working nicely so far for my rewrite of my web site. Writing Classic ASP style again is taking a little getting used to again though, the visual preview from the designers made styling the page a lot nicer.

The lack of control designers also seem like it would hinder having a graphics guy using Expression Web do the UI with MVC based web applications. But I have never worked with a graphics guy on a project that way anyway so I am could be wrong.

 

It would also be nice if the method used by the Route class to parse the Url was virtual, so I could subclass it and allow me to parse something like:

/Example/Simple/Form/MultiPageForm/ShowSource/

to go to the Examples controller, going into the following controller action

[ControllerAction]
public void ShowSource(string[] Categories, string ID)

which would allow me to have a consistent directory scheme for both the ASP.Net examples, along with the Classic ASP examples that are already available.

I could probably do something like /Example/Simple_Form/MultiPageForm/ and use [Controller]/[Category]/[ID]/[Action] but I would prefer it to get to the controller action pre-parsed.

Technorati Tags:

Generic begin/end Html tag extension method

After working on the login usercontrol, I decided that I wanted to add similar functionality to the navigation sections of the site for accounts/roles that didn’t get ads displayed. So I needed a standard way to put dynamic sections into a page.

I liked the syntax used by the form HtmlHelper methods, so decided to base it off of the SimpleForm class and ended up with this

//Based on the SimpleForm class in MvcToolkit 
//Wish I believed I would have ever thought to use
//IDisposable to do this
public class SimpleWrappingTag : IDisposable
{ protected string _beginTagFormat = "<{0} {1}>"; protected string _attributeFormat = "{0}="{1}" "; bool _startTagRendered = false; bool _endTagRendered = false; protected IHttpContext _context; protected object _htmlAttributes = null; //Not letting this be modified outside the class for now //might change later public string TagName { get; protected set; } //Subclassed controls can put their class specific info here public SimpleWrappingTag(string tagName) { this.TagName = tagName; } public SimpleWrappingTag(string tagName, IHttpContext context , object htmlAttributes) { this.TagName = tagName; this._context = context; this._htmlAttributes = htmlAttributes; } /// <summary> /// Creates a StringBuilder and passes it to an overloaded method. /// Override this method for attributes that should be first in tag. /// </summary> /// <returns></returns> protected virtual StringBuilder BuildAttributeList() { return BuildAttributeList(new StringBuilder()); } protected virtual StringBuilder BuildAttributeList(StringBuilder sb) { sb.Append(_htmlAttributes.ToAttributeList()); return sb; } //Method orginally from SimpleForm, but changed to work with //BuildAttributeList instead of BuildFormOpenTag public void WriteStartTag() { if (!this._startTagRendered) { string formTag = String.Format("<{0} {1}>", TagName , BuildAttributeList()); this._context.Response.Write(formTag); } } public void WriteEndTag() { if (!this._endTagRendered) this._context.Response.Write(String.Format("</{0}>", TagName)); } public void Dispose() { WriteEndTag(); } }

Next I made some trivial, but needed extension methods for the HtmlHelper class.

public static class DevExamplesExtensions
{
    public static IDisposable HtmlTag(this HtmlHelper helper, string tagName)
    {
        return helper.HtmlTag(tagName, null);
    }
    public static IDisposable HtmlTag(this HtmlHelper helper
        , string tagName, object htmlAttributes)
    {
        SimpleWrappingTag tag =  new SimpleWrappingTag(tagName
            , helper.ViewContext.HttpContext, htmlAttributes);
        tag.WriteStartTag();
        return tag;
    }
}

And while I’m satisfied with how this turned out, though I’m hoping to be able to delete the code at some point, I don’t like how the code I wrote to implement an Ajax.UpdatePanel method turned out. So I’m not going to post it at the moment.

But it was going to look something like

public static UpdatePanel(this AjaxHelper helper, string panelId, ….)
{
   helper.ViewContext.HttpContext.Write(“update panel js….”);
   IDisposable tag = new HtmlHelper(helper.ViewContext.HttpContext)
        .HtmlTag(“div”,new { id=panelId});

}

Below is a list of things I couldn’t think of a good solution for at the moment

  1. I didn’t like the fact that I was putting the actual JavaScript into the UpdatePanel extension method. Rob Conery said something on the forums about using services to provide the view with site-wide info that seemed interesting, but not sure of a good way to implement this would be.

    It would be nice to have service providers kind of like you can use in Windows Workflow Foundation or VS control designers, that would let me add a IScriptService to do the actual JavaScript coding based on the script library I wanted to use.

    Maybe I should just create a script provider for this.

  2. Having to pass in a list of “triggering” controls felt kind of clunky. I’m trying to think of the best way to allow me to specify that a Html.ActionLink should register itself with the “UpdatePanel”.

    Most of what I think of for this, basically requires me to implement my own versions of the stuff already implemented in the MvcToolkit.

  3. I couldn’t come up with a clean way to have the panel in the Usercontrol, but only have it be done if the usercontrol is called from a page instead of as a standalone view. I guess I could have the controller tell it this, but ideally they would just kind of know.

I think I may have already thought of the solution #3, and a workable #2. But I am really hesitant to do anything with #1 (outside the provider maybe) since I doubt I would do it close enough that I wouldn’t need to remove it all to move over to their way, should they implement something like service providers.

I think I’m going to put this aside for a while on another part of the site, this just is a “nice to have” feature, and get some of the other pieces that I actually need to have for the site done.

 

 

 

* 4 actually, but I said how I wished I could implement an interface using an anonymous type.