Create a custom HtmlHelper.TextBoxFor() to display label text as “placeholder” integrated with twitter bootstrap

We have TextBoxFor() and LabelFor() in MVC, they are binded with my model. If you are using twitter bootstrap and want to display the model property label as a placeholder in textboxes, what should you do.

Here is what I have done.

My model:

public class User
{
    [Display(Name="User name")]
    public string Username {get;set;}
}

Normally in the view we put,

@model User

<ol>
    <li>
        @Html.LabelFor(p=&gt;p.Username)
        @Html.TextBoxFor(p=&gt;p.Username)
    </li>
</ol>

image

If you want to display it as placeholder in twitter bootstrap,

image

Let’s create a TextBoxPlaceHolderFor() extension method of the htmlhelpers, remember to reference the namespace,

using System.Web.Mvc.Html;

So you can re-use the HtmlHelper.TextBoxFor() in your TextBoxPlaceHolderFor() method.

Here is the code with three overloads,

public static class TextBoxForExtensions
    {
        public static MvcHtmlString TextBoxPlaceHolderFor(this HtmlHelper html, Expression<Func> expression, object htmlAttributes)
        {
            var dict = new RouteValueDictionary(htmlAttributes);
            return html.TextBoxPlaceHolderFor(expression, dict);
        }
        public static MvcHtmlString TextBoxPlaceHolderFor(this HtmlHelper html, Expression<Func> expression)
        {
            var htmlAttributes = new Dictionary();
            return html.TextBoxPlaceHolderFor(expression, htmlAttributes);
        }

        public static MvcHtmlString TextBoxPlaceHolderFor(this HtmlHelper html, Expression<Func> expression, IDictionary htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
            if (!String.IsNullOrEmpty(labelText))
            {
                if (htmlAttributes == null )
                {
                    htmlAttributes = new Dictionary();
                }
                htmlAttributes.Add("placeholder", labelText);
            }
            return html.TextBoxFor(expression, htmlAttributes);
        }

    }

When you call the methods you can do,

@Html.TextBoxPlaceHolderFor(m => m.UserName)

//or 

@Html.TextBoxPlaceHolderFor(m => m.UserName, new { @class="form-field" })


You are done. Now get your form neat and clean using the TextBoxPlaceHolderFor().

My problem with SimpleMembership, MVC4 and AuthorizeAttribute and Roles

I have created an internet application using the MVC4 template with SimpleMembership.

It comes with a “InitializeSimpleMembershipAttribute” which initialize (create) the database if it is not exist. The InitializeSimpleMembershipAttribute attribute is added to the account controller.

Now if I put [Authorize] or [Authroize(Users=”administrator”)] in action method. When I direct to the URL, it gives me an error:

Server Error in ‘/’ Application.

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

SQLExpress database file auto-creation error:

The connection string specifies a local Sql Server Express instance using a database location within the application’s App_Data directory. The provider attempted to automatically create the application services database because the provider determined that the database does not exist. The following configuration requirements are necessary to successfully check for existence of the application services database and automatically create the application services database:

I spent quite a bit of time figuring out this. What I did is, putting the line “WebSecurity.InitializeDatabaseConnection” to the Global.asax file. That ensures the database connection is initialized as early as possible.

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

Then I move the filter from AccountController to the FilterConfig.cs file. So when the filters are registered, it calls the InitializeSimpleMembershipAttribute as well.

filters.Add(new InitializeSimpleMembershipAttribute());

I hope this may help people who is having the same problem.

ajax request only action filter, MVC

I created a handy ajax request filter, that you can apply to your ajax action method call.

    public class AjaxRequestAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if(!filterContext.HttpContext.Request.IsAjaxRequest())
                	//do something
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {

        }
    }
    [AjaxRequest]
    public ActionResult AjaxActionMethod()
    {
        		//to do
    }

Cool features of ASP.NET MVC 4

I have been played around with MVC 4 for a while, now it is finally live.

I found there are quite a few great features included in MVC 4. Here I am going to chat about my favourite ones.

1. Extension to razor scripts

The default view engine supports, HTML attributes starting with ~/ will now be automatically replaced with the application root, developers no longer need to use the Url.Content function.

Another big time saver is conditional attributes. If the @styleClass variable in class="@styleClass" is null, the entirely attribute is automatically removed for you.

2. CSS & JS bundles

a. Instead of listing each css/js file needed by the client, I can use bundle to point to a specific folder.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));

b. You can control the bundling and minification in web.config by turning compilation debug = true or false. Or you can override it from RegisterBundles() method

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));

    // Code removed for clarity.
    BundleTable.EnableOptimizations = true;
}

c. bundle is cached on the browser for one year. It sets the http header one year from when the bundle is created.

d. It supports LESS style sheet, by adding “dotless” NuGet package to your project.

implement the IBundleTransform interface,

using System.Web.Optimization;

public class LessTransform : IBundleTransform
{
    public void Process(BundleContext context, BundleResponse response)
    {
        response.Content = dotless.Core.Less.Parse(response.Content);
        response.ContentType = "text/css";
    }
}

and create the bundle of LESS files and CssMinify transform in RegisterBundles() method in BundleConfig.cs file.

var lessBundle = new Bundle("~/My/Less").IncludeDirectory("~/My", "*.less");
lessBundle.Transforms.Add(new LessTransform());
lessBundle.Transforms.Add(new CssMinify());
bundles.Add(lessBundle);

Add it to the view,

 @Styles.Render("~/My/Less");

3. WebAPI

  • Allows the building of HTTP APIs that automatically can serialize to the format requested such as xml/json
  • Support oData so that if the returned object support iQueryable parameters can be added to the return to subsets (paging, top n etc)
  • Allows hosting of WebAPI either in an area web, console, service, windows 8
  • Allows results to easily return custom HTTP response codes and location header for querying data

4. Mobile view engine,

  • Supports adaptive rendering using media queries
  • Allows creation of different mobile specific views
  • Supports mobile templating engines such as jQuery mobile
  • 5. Real time communication

  • Uses SignalR.
  • .NET way of doing what everyone is using node.js for.
  • Allows the server to call JavaScript, e.g pushes a call to the browser thus executing some JavaScript