Double Input problem with CheckBoxFor in MVC while serializing

if you have tried to serialize a CheckBoxFor from MVC to JSON, you will notice that you get two inputs, and it can mess up the data you are sending

It's no surprise that JavaScript is not sure how MVC works so when you try data.serialize() on MVC form data, you get odd results. Here is a simple workaround for when you need something to be serialized. I modified the GetPropertyName method from this post on StackOverflow.
public static string GetPropertyName<TModel, TValue>
    (Expression> exp)
{
    MemberExpression body = exp.Body as MemberExpression;
    if (body == null)
    {
        UnaryExpression ubody = (UnaryExpression)exp.Body;
        body = ubody.Operand as MemberExpression;
    }
    return body.Member.Name;
}

public static MvcHtmlString CheckBoxForJson<
    TModel, TValue>(this HtmlHelper<TModel> helper, 
    Expression<Func<TModel, TValue>> expression)
{
    string propName = GetPropertyName(expression);
    string html = "<input type=\"checkbox\" name=\"" 
        + propName + "\" id=\"" 
        + propName + "\" value=\"true\" />";
    return MvcHtmlString.Create(html);
}

And use it like this:
@Html.CheckBoxForJson(x => x.SomeBool)

The reason for the 'true' is because otherwise it will always pass as false since 'on' is not a bool value (html default).

MVC Html Helper for including an Id with a DisplayFor

there are cases when you want to include an id with your DisplayFor()

public static MvcHtmlString DisplayWithIdFor(
    this HtmlHelper helper, 
    Expression> expression, 
    string wrapperTag = "div")
{
    var id = helper.ViewContext.ViewData.TemplateInfo
        .GetFullHtmlFieldId(ExpressionHelper
            .GetExpressionText(expression));
    return MvcHtmlString.Create(
        string.Format("<{0} id=\"{1}\">{2}", wrapperTag, 
        id, helper.DisplayFor(expression)));
}

It is used like this:
@Html.DisplayWithIdFor(x => x.Name)
<!-- to produce -->
<div id="Name">Bill</div>

Or if you want to wrap it in a non-div:
@Html.DisplayWithIdFor(x => x.Name, "span")
<!-- to produce: -->
<span id="Name">Bill</span>
    

inline asp.net tags... sorting them all out (<%$, <%=, <%, <%#, etc.)

There are all sorts of different inline tags, and I haven't found a place that explains them all in one place, so here is the quick and dirty...

*UDPATED 2012-02-22: Thanks to Conrad Buck and Austin for updates!

<% ... %>

The most basic inline tag, basically runs normal code: 

<% if (User.IsInRole("admin")) { %>
    You can see this
<% } else { %>
    You are no admin fool!
<%} %>

http://msdn2.microsoft.com/en-us/library/ms178135(vs.80).aspx

 

 

<%= ... %>

Used for small chunks of information, usually from objects and single pieces of information like a single string or int variable: 

The Date is now <%= DateTime.Now.ToShortDateString() %>
The value of string1 is <%= string1 %> 

http://msdn2.microsoft.com/en-us/library/6dwsdcf5(VS.71).aspx

*note: <%= is the equivalent of Response.Write() -  Courtesy of Adam from the US,thanks!

 

 

<%# .. %>

Used for Binding Expressions; such as Eval and Bind, most often found in data controls like GridView, Repeater, etc.:

<asp:Repeater ID="rptMeetings" DataSourceID="meetings" 
    runat="server">
    <ItemTemplate>
        <%# Eval("MeetingName")%>
    </ItemTemplate>
</asp:Repeater>

http://msdn2.microsoft.com/en-us/library/ms178366.aspx

 

 

<%$ ... %>

Used for expressions, not code; often seen with DataSources: 

<asp:SqlDataSource ID="party" runat="server" 
    ConnectionString="<%$ ConnectionStrings:letsParty %>" 
    SelectCommand="SELECT * FROM [table]"
/>

http://msdn2.microsoft.com/en-us/library/d5bd1tad.aspx

 

 

<%@ ... %>

This is for directive syntax; basically the stuff you see at the top your your aspx pages like control registration and page declaration: 

<%@ Page Language="C#" 
    MasterPageFile="~/MasterPage.master" 
    AutoEventWireup="true" CodeFile="Default.aspx.cs" 
    Inherits="_Default" Title="Untitled Page" %>
<%@ Register TagPrefix="wp" Namespace="CustomWebParts" %>

http://msdn2.microsoft.com/en-us/library/xz702w3e(VS.80).aspx

 

 

<%-- ... --%>

This is a server side comment, stuff you don't want anyone without code access to see:

<asp:Label ID="lblAwesome" runat="server"/>
<%-- sometimes end users make me angry --%>
<asp:LinkButton ID="lbEdit" Text="Edit" OnClick="Edit_Click" runat="server" />

http://msdn2.microsoft.com/en-us/library/4acf8afk.aspx

 

<%: ... %>

This tag is identical to the "<%= ... %>" tag except that it auto-html-encodes the value within the tag. As Phil Haack said: I often tell people it’s <%= but with the = seen from the front.:


<%: Html.TextBox("FirstName") %>

http://haacked.com/archive/2009/09/25/html-encoding-code-nuggets.aspx

 

And that's that.  

kick it on DotNetKicks.com

Using a Custom Controller Class in Asp.Net MVC to Simplify Coding

Controllers often have some repetitive code, implementing your own Controller class can help eliminate a lot of this

Here is a small snippet and how I use some simple tricks to help clean up my Controllers in Asp.Net MVC (using MVC 4 at the moment):
public class MyController : Controller
{
    public MyEntities Db { get; set; }

    protected override void OnActionExecuting(
        ActionExecutingContext filterContext)
    {
        if (filterContext.IsChildAction)
            return;
        this.Db = new MyEntities();
        base.OnActionExecuting(filterContext);
    }

    [HttpPost]
    public ActionResult Index(FormCollection form)
    {
        string srch = form["Search"] ?? string.Empty;
        return RedirectToAction("Index", 
            new { search = srch });
    }

    protected void AttachToDb(EntityObject obj, 
        bool save = false, string entityKeyField = "Id")
    {
            obj.EntityKey = new EntityKey(
                obj.ToPluralizedString(), entityKeyField, 
                obj.GetType().GetProperty("Id")
                .GetValue(obj, null));
            Db.Attach(obj);
            Db.ObjectStateManager.ChangeObjectState(
                obj, System.Data.EntityState.Modified);
            if (save) Db.SaveChanges();
    }
}

The first thing in the code is simple declaration of an EntityContext - this is implemented directly, but could (and usually should) be implemented differently for dependency injection, but you get the idea. Here is where I also like to include stuff that is often used and could be vital (and centralized) for an application like an output type for web services (JSON, XML, etc.).

Next the OnActionExecuting is over-ridden and the Context is initialized. Here is where you can initialize the properties you set above.

The next method, the HttpPost Index method is just an example of how often times you can consolidate a commonly used method. For this example, it was from an application that had searches on all index pages. Instead of repeating this code in every controller, you can just put it here.

The final method has become very useful. A use I often find, is when taking in a large model after an Asp.Net MVC POST event, I can attach the model to the Db generically without any extra work

This method is a bit confusing, but it is simply attaching the new model to the Db without a Db lookup. In my tables, I generally have a field 'Id' that houses the Primary Key of every table, whether it is an Int or Guid. This way, I can simply pass in whatever object I am currently working with, and by using the pluralize method, and reflection, the method can figure out which table to attach the model to - eliminating the need for me to do extra coding. Alternatively, if I want to change the Key from 'Id', I can pass that in as well.

Now when I get a model being POSTed, it is easy to deal with:
[HttpPost]
public ActionResult Edit(Widget model)
{
    if(ModelState.IsValid)
    {
        AttachToDb(model, true);
        //do stuff
    }
    else { /*do other stuff*/ }
}

This avoids the need to take another trip to the DB, change the properties on the object, then submit - streamlining the process very much and cutting down a lot of code.

This would be an example of how this would be done manually with the normal Controller class:
[HttpPost]
public ActionResult Edit(Widget model)
{
    if(ModelState.IsValid)
    {
        MyEntities db = new MyEntities();
        Widget w = db.Widgets.Single(x => x.Id == model.Id);
        w.Name = model.Name;
        w.Serial = model.Serial;
        db.SaveChanges();
        //do stuff
    }
    else { /*do other stuff*/ }
}

Not a huge difference when you are just getting 2 values, but you could see how a model with 20 or 30 fields can be cut down from 30+ lines to just 1 or 2.

Constraining Routes in MVC to an Enum the Easy Way

simple way to constrain a route to only allow enum values

Say I have the following enum:
public enum SearchType { Facilities, Courses, Exercises};

And I only want those the be available in route Search/{SearchType}. I could constrain it manually with a string, but then what if the enum changes and I have this in a bunch of routes? Here is a simple way to accomplish this constraint:
public static void RegisterRoutes(RouteCollection routes)
{
    List searchTypeL = new List();
    foreach (Enums.SearchType type in 
        Enum.GetValues(typeof(Enums.SearchType))) 
    { searchTypeL.Add(type.ToString()); }
    string searchTypes = string.Join("|", searchTypeL);
    
    routes.MapRoute(
        "Searches",
        "Search/{type}",
        new { controller = "Search", action = "Index" },
        new { type = searchTypes }
    )
    ...

Very basic, all this does is enumerate through your enum and create a simple string to filter with.

ReCaptcha - Getting the Challenge Key and/or image with Asp.Net MVC

Often times you do not need the whole deal, or you are working with a technology that doesn't employ javascript or iframes

Recently I was working on a project that needed to provide (via MVC 3) the ReCaptcha image and/or challenge key only, and not the whole html/javascript portion due to limitations by the data consumer. It took me a while, but there is quite an elegant and simple solution to this.

Here is the controller I came up with:
public class CaptchaController : Controller
{
    public string contentReturnType = "text/plain";
    public string googleChallengeUrl = "http://
        www.google.com/recaptcha/api/challenge?k={0}";
    public string googleImageUrl = "http://
        www.google.com/recaptcha/api/image?c={0}";
    public string googleImageHtml = "<img style=
        \"display: block; \" height=\"57\" width=\"300\" 
         src=\"{0}\"/>";

    [HttpGet]
    public ContentResult GetChallengeKey(
        string proxyIpAndPort = null)
    {
        string http = string.Format(googleChallengeUrl, 
            ReCaptchaValues.PublicKey);
        WebClient client = new WebClient();

        //assuming no proxy on a local machine
        if (!string.IsNullOrEmpty(proxyIpAndPort) && 
            !Request.IsLocal) 
        {
            client.Proxy = 
                new WebProxy(proxyIpAndPort, true);
        }

        string html = client.DownloadString(http);
        int start = html.IndexOf('{');
        int length = html.IndexOf('}') - start + 1;
        string json = html.Substring(start, length);

        ReCaptchaState state = 
            new JavaScriptSerializer()
                .Deserialize(json);
        return this.Content(state.challenge, 
            contentReturnType);
    }

    [HttpGet]
    public ContentResult GetImageUrl()
    {
        return this.Content(string.Format(googleImageUrl, 
            GetChallengeKey().Content), contentReturnType);
    }

    [HttpGet]
    public ContentResult GetImageHtml()
    {
        return this.Content(string.Format(googleImageHtml, 
            GetImageUrl().Content), contentReturnType);
    }
}

This is using json deserializing of the ReCaptcha return string into a .Net object named ReCaptchaState which is covered here.

Now all that you need to do is call one of the urls to get the desired result in a plaintext format (you can change the output if you wish).

Forganizer - unobtrusive network file organizer - new open source project

An unobtrusive intranet ASP.NET MVC application for logically tagging, organizing and searching network files in one centralized location with a fast and simple interface

Me and some friends have a network set up where we share movies and music. This is a Windows domain network and we all simply share our folders as 'shares' across the network. The problem is that there are so many different files and they are all spread out, there was no way to browse them all at once in any sort of convenient way. That is where the idea for forganizer came up, it is simply a tagging and search interface for multiple shared drives (or just your local ones if you want). Since I hadn't really made any MVC projects yet, I decided to do this one in ASP.NET MVC, a great new technology. Also, this was my first attempt at many new programming techniques I hadn't really used in the past such as Unit Testing, Inversion of Control (Dependency Injection) and Mocking, all very useful!

I want to say right up front, this is for a Windows network, and will work best with... err... IE7+, because it works best with your file explorer - some features like folder opening and downloads may not work with other browsers.

You can always check out my source code if you want to see how something was done, here I am just going to explain what the program does from a user point of view.

clean install

Once forganizer is installed (just run Content/setup.sql and publish the rest to a website, making sure you have MVC installed and all that good stuff) you will see this:

Now you need to add some files to the system, here is the directory we are going to add for the demo. Notice that there are some files in the top folder, and also some folders that go down (quite a few nested folders actually).

adding some files

To add new files in, simply click on the 'manage' tab on the upper right. The default page for manage is 'add files' so you simply enter the network path in the 'from folder' field and click 'run it'.
Notice that it only uploaded 8 files, those are the files in the root. If you check the 'recursive' checkbox, if will go ahead and run through all of the files regardless of depth:
The system will never add a file more than once, so feel free to run the same folders over and over, in fact, that is how you enter new files that have been put on the shares - I think later I will implement and auto-updater. Now if we were to will in more of the textboxes the system would be more selective. Say I wanted to exclude all of the .txt files I have, I would just fill '.txt' in the 'exclude extensions' blank. Similarly, if I am only interested in video files, I would just put '.avi .mpg .mpeg' in the 'include only these extensions' field - it's really pretty self-explanatory.

now you are up and running

Click on the 'search' tab or on 'forganizer' and you will see that you now have a tidy list of files. Also, you will notice that on the right side, all of the file extensions that were in your folders are now represented in the extensions cloud, sized by the relation of file count - in my example, there are many more .cs files than anything else:
Each file has download, open folder and delete links next to it. They all do what you think they would, except delete does not actually delete a file, just the reference in forganizer. If you delete a reference, then later restore it, it will still hold all the tags you previously assigned to it.

tag some stuff

As of right now, this doesn't do us much good, they are searchable by file extension (just click on the file extension on the right), but you could do that in Explorer. We want to add some tags, so click on 'manage' again, and then on 'mass tag adding' on the right side menu.
In this example, I am adding the tag 'Testing' to all the files in the directory \\network_drive\share\folder\forganizer\Forganizer.Tests. Now go back to the search, and you can see that many of the files have been tagged:
The 'mass tag delete' and 'mass tag edit' work just the same as above (actually runs the same exact code). Notice that I also manually added the 'wallpaper' tags to a couple .jpg files - that was done simply by typing 'wallpaper' in the small textbox by each file and clicking '+tags' or pressing enter. You will also see that now there is a cloud tag on the right showing the tags that are in the present search.

create categories

Now you can make some categories to make searching easier. Categories are just groups of file extensions, I am going to make a 'programming' category that includes .js and .cs files:

the manual tagging interface

Now going back to the main search, you will see that a 'programming' category is now in the sidebar. In the following picture, you can see that I have clicked on the 'WebUI' tag and the '.js' file extension. Now all I see is the .js files that are tagged with 'WebUI', it's just that simple! Also take note of the intuitive urls achieved with MVC.
I also typed MS in some of the .js file blanks as I am going to tag those as MS javascript files by pressing enter:
Those MS tags are now inserted.

Now if you want to delete a tag, simply hover over it and a [delete] link will show up:
Click it and the tag is removed:
Pretty basic stuff and simple to figure out and use. This same add/delete interface is used for categories as well.

file cleanup

Now what if someone went and deleted some files, since forganizer does not actually constantly monitor the files, it will be out of date. That is why I built a cleanup feature - say I delete these files:

I can just go to manage -> file cleanup and click the big button:
And you are all cleaned up. One great feature on this is if any file is deleted, either manually or by the cleanup tool, its tags will be preserved; if that file is ever re-added, or restored, it will still have all the meta-data that it always had.

some more stuff

I went ahead and added the 'WebUI' tag to all the files in the \\network_drive\share\folder\forganizer\forganizer.WebUI folder, and 'DomainModel' to all files in the \\network_drive\share\folder\forganizer\forganizer.Tests folder, and finally 'forganizer' to all the files in the \\\network_drive\share\folder\forganizer\forganizer folder, so I can easily discern all of those files. I also added a 'visual_studio' category that include .csproj, .sln and .suo extensions, as well as a documents and images category.

So now I want to find all the Visual Studio related files in forganizer; all I need to do is click on 'visual_studio' in the categories, and 'forganizer' in the tags section and I get the files I am interested in:
Think of it now as "showing all the .csproj, .sln and .suo files with the forganizer tag" Notice that in the upper right, 'and' has a box around it, you can also choose 'or' and it will be a broader search. Say I clicked the 'or' link and then clicked the 'wallpaper' tag and 'images' as well, now forganizer would be showing "showing all the .csproj, .sln, .suo, .png, .jpg and .jpeg files with the forganizer tag OR the wallpaper tag"
You will also see that each cloud (tags/extensions/categories) will be broken into 2 parts, the active (green) links and the inactive (grey) links. The active links are files that are showing in the search right now, the inactive ones are things you can add to the search that will broaden it; if you have 'and' picked in the tag section, you will not see and inactive tags, as that wouldn't make sense.

remember, this is all unobtrusive

This never actually does anything with the files, deleting only deleted the reference, the files will still be there! This is just a layer on top to help sort/search.

I hope this is interesting to someone out there, if not, it was great to help learn MVC and some other great technologies.

Setting up Castle Windsor IoC (Inversion of Control) aka Dependency Injection

it can be a bit confusing getting this thing running

Dependency Injection is the new big thing, and I am late on that bandwagon. But I recently began using Castle Windsor while learning ASP.NET MVC through reading Pro ASP.NET MVC Framework which is a fantastic book.

Anyway, setup can be a little pain to go through, and is no longer exactly as written out by the book, so here is a quick and simple guide:

download/reference

  • Visit the Project Page and look for the MicroKernel/Windsor project, download the latest stable version (it was 2.0.0 while writing this).
  • Copy the dlls to your bin or register them in your GAC.
  • Reference the following libraries:
    • Castle.Core
    • Castle.DynamicProxy2
    • Castle.MicroKernel
    • Castle.Windsor

alter your web.config

Add in the following inside the <configSections$gt;

<section name="castle" type="Castle.Windsor.Configuration.AppDomain. CastleSectionHandler, Castle.Windsor" />


Add this right before your <system.web>

<castle><components></components></castle>


that's it

That's all it takes, your Castle Windsor should now be running.

Slick-Ticket v2.0 Released

Many improvements across the board, mostly behind the scenes

I am proud to say that I have released version 2 of my open-source trouble-ticketing/help desk system Slick-Ticket. I wasn't initially planning on making a new release, but the program has become suprisingly popular with over 3,000 downloads and an actual (small) community of users which is great!

You can download Slick-Ticket v2.0 if you have never used it before. If you have already been using a previous version, you will need to replace your existing code with the patching program, run it, then download version 2. It does a few database modifications to cleanup the lack of seperation of markup/db which was done very poorly in a rush of the first version. As with any upgrade, I highly recommend you backup prior to running this upgrade!

improvements

  • Broke the dbi.cs class up into more discreet classes
  • Renamed many methods properly
  • Removed (non-user-added) markup from any of the database fields
  • Moved some markup from the code-behinid to the .aspx pages
  • Globalized and ready for translation
  • Added ability to possibly delete attachments/comments/tickets in the future
  • Introduced some more dependency injection
  • Code is now much more robust!