Showing posts with label asp.net mvc. Show all posts
Showing posts with label asp.net mvc. Show all posts

Tuesday, 30 April 2013

Using Web API filter for Polymorphic results

When starting a little deeper with Web API I found a block on the road: if I returned any object different of the return type declared in the action method signature, then the serialization mechanism throw an exception related to the type instantiated is not expected, the error message is like this: "Type 'Mvc4AppFilter.Models.Student' with data contract name 'Student:http://schemas.datacontract.org/2004/07/Mvc4AppFilter.Models' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer." when trying to serialize as XML, JSON works like a charm, why is this happening?
If we find the source code for class System.Net.HttpHttpRequestMessageExtensions at method with this signature, because there are several overloads:
public static HttpResponseMessage CreateResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value, HttpConfiguration configuration)
We found the things related to content negotiation and checking for proper values from configuration, but at the end there's something like this:
return new HttpResponseMessage
{
    Content = new ObjectContent<T>(value, result.Formatter, mediaType),
    StatusCode = statusCode,

    RequestMessage = request
};
and the key point is that if the typeof(T) is not equal to value.GetType() then the ObjectContent throws the exception because of the mismatching of types and that occurs when for example we declare the method with return type Person and for some reason we return either a Worker object or Student object (where both inherit from Person)

The first solution was to extract the important sentences from this source code and create my own extension for CreateResponse and using the ObjectContent non generic version, but later I decided to group this code in a Filter, in this case an Action filter, and it will be executed after each action is executed, the goal is to transform the any object return type action to a properly configured HttpResponseMessage. Here's the code.
public class HttpResponseFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var request = actionExecutedContext.Request;
        var response = actionExecutedContext.Response;
        if (response.Content != null && !response.Content.IsHttpResponseMessageContent() && response.Content is ObjectContent) 
        {
            var objContent = response.Content as ObjectContent;
            var value = objContent.Value;
            var result = request.CreateResponse(System.Net.HttpStatusCode.OK);
            if (value != null)
            {
                var config = request.GetConfiguration();
                var negociator = config.Services.GetContentNegotiator();
                var nresult = negociator.Negotiate(value.GetType(), request, config.Formatters);
                result.Content = new ObjectContent(value.GetType(), value, nresult.Formatter);
            }
            actionExecutedContext.Response = result;
        }
    }
}

Finally, we need to register the filter in application startup, i.e. in the file out of the box WebApiConfig.cs by adding this line:
config.Filters.Add(new HttpResponseFilter());
Hope it helps you to improve your code, the source can be downloaded here.

Monday, 2 July 2012

Upload very large files - Part 2

Earlier in this blog I talked about the general idea behind one solution for uploading very large files (I consider very large when they are above 2GB), how the file API is becoming more popular and the possible client side approaches. This time I’ll describe the server side part of the solution. As a quick reminder, the server is responsible for:

  • To determine if the request is to be handled by the mechanism, if not, just let it go.
  • To determine if the request is an initial packet or a data packet.
  • To handle properly each type of packet giving the appropriate response so the client can continue.

This is part of a bit more complex solution, named FreshUplaod, which has the Server component and client components using either JavaScript or Silverlight. The core element is the UploadHelper class, as the name indicates is a helper, it encapsulates the dirty logic regarding the request data reading and processing all stuff.

The methods ProcessInitialPacket and ProcessDataPacket do the actual work, but it’s necessary to know if the request data corresponds to one or another, that’s the job for these other methods IsInitialPacket and IsDataPacket. The actual helper utility is another method, ProcessRequest that acts as a façade to the whole mechanism. An example on how to use it is as follows:

[HttpPost]
public ActionResult Upload(FormCollection collection)
{
    var packetSize = 4 * 1024 * 1024; // default to 4 MB
    var filePath = Server.MapPath("~/_temp_upload/");

    var result = UploadHelper.ProcessRequest(
        Request, filePath, packetSize);

    if (result != null)
        return Json(result);
    return Content("");
}
 

This is using a controller action on ASP.NET MVC 3, where the access to the request is quite easy and the conversion to Json is stress-free too. The key points here are the packet size and the folder where the file is to be stored, the packet size must be exactly the same configured on client side in order to expect a good behavior, I’ve used the 4 MB value because this is the default constraint imposed by ASP.NET and of course this can be tweaked as you want in web.config file.

Now let’s see how to use this element on ASP.NET WebForms, the idea I suggest here is to use a handler whether it was a Generic Handler or ASP.NET Handler, it can be also a WebForm but is not elegant enough solution because the WebForms are chained in a different pipeline and there can be a bit of noise, although it work as well. Here’s the code sample:

public void ProcessRequest(HttpContext context)
{
    var packetSize = 4 * 1024 * 1024; // default to 4 MB
    var filePath = context.Server.MapPath("~/_temp_upload/");

    var result = UploadHelper.ProcessRequest(
        context.Request.RequestContext.HttpContext.Request, 
        filePath, packetSize);

    if (result != null)
    {
        JsonResult(context.Response, result);
    }
    else
    {
        context.Response.Write("");
    }
}

private void JsonResult(HttpResponse response, object result)
{
    response.ContentType = "application/json";
    var serializer = new JavaScriptSerializer();
    var json = serializer.Serialize(result);
    response.Write(json);
}
 
 

Here we have a little more hand work but not so much, the json conversion and output is done completely manual (if some WebForms people knows how to achieve this with fewer code, please let me know cause I’m a little out of this part of ASP.NET, although I support Scott Hanselman with his slogan that “Only One ASP.NET”). The other key point is how to get the Request but with an instance of HttpRequestBase class, the default context.Response is an HttpRequest instance, so after some minutes of try-error-retry I found this way to get right value, again if some knows a better way to do it, you know.

In the next posts I’ll cover the other parts of this solution. The whole source code can be found at https://bitbucket.org/abelperezok/freshupload, I am still preparing the code samples so in a few weeks they will be ready.

Friday, 30 March 2012

Language selector in ASP.NET MVC 3 - Part 3

In the last post I talked about implementing a custom route in order to improve the route handling work to support multiple languages in a web application. This custom route would remove the need of duplicate the route (with and without the language parameter) and in the first part of this series I showed an example where the view rendered the language selector using ActionLink for generating the urls, and the collection to iterate was expected to be as part of the view model.

But this is not always possible to do, in fact, the most common scenarios I’ve dealt with, involve putting this kind of component in a common place such as the Layout page or even a partial which is included in Layout page, but less frequent in a dedicated view. To achieve this separation, it’s common to use a Child Action for invoke a controller, which is going to execute an action and return usually a partial view.

If we take the solutions previously discussed and make a little refactoring: create an action (LanguageList) in the languages controller and move the code that renders the links to a partial view (_langSelector) and go to layout page and invoke it as:

@Html.Action("LanguageList", "Langs")

Sure you are going to see the results. The controller action should be like this:

[ChildActionOnly]
public ActionResult LanguageList()
{
    var langs = LanguageProviders.Current.GetList();
    return PartialView("_langSelector", langs);
}

The HTML rendered looks like this:

<a href="/Langs/LanguageList">English</a> 
<a href="/es-ES/Langs/LanguageList">Espa&#241;ol</a> 
<a href="/fr-FR/Langs/LanguageList">Fran&#231;ais</a> 

As you can see, the urls always point to controller Langs and action LanguageList instead of pointing to current controller and action, why does it happen?

When we invoke a child action, a new request is started to the target action, that means, when the route asks for current request values, it obtains those from the new request, which means, the “original” route values were lost at the moment of making the child request.

As these values were lost, my solution is simply to provide them via parameter at invocation time. Once in the controller, the values must be passed to the view, may be using the ViewBag or even a more sophisticated solution could involve the creation of a view model with these data ready to be read by the view.

Having said that, here is the quick solution:

The controller action

[ChildActionOnly]
public ActionResult LanguageList()
{
    ViewBag.CurrentValues = RouteData.Values["CurrentValues"];
    var langs = LanguageProviders.Current.GetList();
    return PartialView("_langSelector", langs);
}

At this point and only to remark, the attribute ChildActionOnly is strongly recommended in order to avoid this action to be called directly or even from an AJAX request if this is not intended to.

The invoke statement in the layout page.

@Html.Action("LanguageList", "Langs", 
 new { CurrentValues = ViewContext.RouteData.Values }
)

The goal of this new parameter is to pass the real current route values to the controller, so it will be able to grab them and pass to the view.

The partial view

@{
    var currentValues = (RouteValueDictionary)ViewBag.CurrentValues;
    var tempValues = new RouteValueDictionary();
    foreach (var item in currentValues)
    {
        tempValues.Add(item.Key, item.Value);
    }
}

@foreach (var lang in Model)
{
    tempValues["lang"] = lang.Code;
    
    @Html.ActionLink(lang.Name, null, tempValues)
    @Html.Raw(" ")
}

At this point, I consider important the lines that make a copy (clone) of the route data received from the controller, otherwise the route values should be modified inside the loop that follows it, and as a consequence, the dictionary will affect the rest of routes in the page, setting the last value in lang.Code forever in the route values if this value were not supplied explicitly when generating the links.

Well, I hope this little sand grain will help you to your day-to-day web programming task, any comment and ideas will be welcome.

Tuesday, 20 March 2012

Language selector in ASP.NET MVC 3 - Part 2

A few weeks ago I talked about giving support to multi lingual applications or i18n for brevity. There I mentioned the strategy I followed using two routes (one including the language parameter and another is just the default) and also I promised to talk more about routes, specially about routes whose goal is match with or without the language parameter. Well, actually I wasn’t too happy with that implementation, but if it isn’t broken, don’t fix it. However, something deep in my mind suspected there must be another solution, I mean, more elegant, while making google research I found an interesting article in codeproject part 1 and part 2. Nice try! But my question was: why to make a custom route class and finally to define the two different routes again at application startup?
I took it as starting point and worked on it, the result: a custom route which is able to deal with the dirty stuff about prepending properly the language fragment and matching from the request url.
The idea is to inherit from the Route class instead of RouteBase, I want to take advantage of the base implementation which is responsible of doing the really dirty stuff, I won’t reinvent the wheel. So the methods to override are GetRouteData and GetVirtualPath.
The custom route must know the default language, it has it as parameter, some comments on GetRouteData method. First, the goal for this method is to determine if the current request must be parsed by us or let it go. Manually split by / and remove the ~ element, after that if there are more than one segment and the first segment doesn’t match the regular expression ^[a-z]{2}(-[A-Z]{2})?$ (commented in the earlier post), then ask to base implementation and if it replies affirmative, set the route value indexed by language parameter to the default language. Otherwise, a little trick with the base implementation, save the current url and prepend {lang}/ to the current and ask to base implementation to check if is valid and finally restore the url value. As you can see, here is when I’ve done the work of two routes in one!
public override RouteData GetRouteData(HttpContextBase httpContext)
{
    var requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
    var segments = requestedURL.Split('/').Where(x => x != "~").ToArray();

    // if request is not localized then call base
    if (segments.Length > 0 && !Regex.IsMatch(segments[0], @"^[a-z]{2}(-[A-Z]{2})?$"))
    {
        var result = base.GetRouteData(httpContext);
        if (result != null)
            result.Values[LangParam] = _defaultLang;
        return result;
    }

    // if request is localized then prepend the culture segment to the url
    var currentUrl = Url;
    Url = string.Format("{{" + LangParam + "}}/{0}", _url);
    var baseRoute = base.GetRouteData(httpContext);
    Url = currentUrl;
    // save and restore the current URL
    return baseRoute;
}
The next step to complete the route’s functionalities is GetVirtualPath which will generate the url according to route map data. Generate the url is a little harder than match the url, but not impossible. Let’s remember how the url generation occurs: if the dictionary received as parameter has all the necessary values for this route, the optional values may be taken from the current request (this will give us the idea of virtual directories commented in an earlier post). So here the important parameter is the language, find it either in current request or explicit values and remove it (the actual route doesn’t have this paramter). Call base implementation and restore each case if necessary (this is important, or the next routes generated since this will have altered values). Finally to prepend language segment if necessary and only if its value is different from the default language. I show here the code.
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
    string lang = "", lnRequest = "", lnValues = "";
    // look for the language param in current request context
    if (requestContext.RouteData.Values.ContainsKey(LangParam))
    {
        // if found then save it in lang variable
        lnRequest = lang = (string)requestContext.RouteData.Values[LangParam];
        // and remove it
        requestContext.RouteData.Values.Remove(LangParam);
    }

    // look for the language param in explicit values 
    if (values.ContainsKey(LangParam))
    {
        lnValues = lang = (string)values[LangParam];
        values.Remove(LangParam);
    }

    // call base method...
    var virtualPath = base.GetVirtualPath(requestContext, values);

    // restore from current request context if necessary
    if (!string.IsNullOrWhiteSpace(lnRequest))
        requestContext.RouteData.Values.Add(LangParam, lnRequest);
    // restore from explicit values if necessary
    if (!string.IsNullOrWhiteSpace(lnValues))
        values.Add(LangParam, lnRequest);

    if (virtualPath == null) return null;

    // prepend language segment if necessary and only if different from the default language
    if (!string.IsNullOrWhiteSpace(lang) && !string.Equals(lang, _defaultLang, StringComparison.OrdinalIgnoreCase))
    {
        virtualPath.VirtualPath = lang + "/" + virtualPath.VirtualPath;
    }
    return virtualPath;
}
Now, it’s time to invoke this brand-new route just implemented, I think it should be as similar as possible to use as the out of the box route, like this:
routes.AddLocalizedRoute(
    "es-ES",                                                                        //The default Language 
    "{controller}/{action}/{id}",                                                   // URL with parameters (Without any sign of i18n)
    new { controller = "SimpleUser", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
In order to achieve this I’ve implemented an extension for the class RouteCollection, like the original MapRoute which is an extension too.

Thursday, 23 February 2012

Language selector in ASP.NET MVC 3

Develop web applications with multi lingual (ML) support is always a very tricky affair, in this globalized world we are living nowadays is almost impossible to keep developing web applications without giving the opportunity to visitors from other languages than ours.

I’ll attempt to share with the community some of my strategies in order to give ML support using ASP.NET MVC 3.0, and I think the next versions will be backward compatible regarding these matters. Let’s start, one of the key points for ML is where to store the current language. There are some well-known places, in the session, in some cookie or even in the url.

Each strategy has its own pros and cons, after digging about the SEO and content indexing (here some SO guys talk about) I decided to choose the url as the ideal place for insert the current language the web is going to be displayed to the client. The general idea is to give the sense of “directories” where the language is the first level and the others contents are languages directories’ “children” in the big web content tree.

Having said that, there is another problem coming up: The route, despite the routing system provided by ASP.NET MVC 3.0 is powerful and very flexible, I have to say it’s something obscure to understand by definition (but not impossible), so let’s use an example on how the url should be:

  • http://www.example.com/directory/content/params
  • http://www.example.com/es/directory/content/params
  • http://www.example.com/fr/directory/content/params

Note that the first sample doesn’t have the language explicitly indicated in the url. This will be the default language defined by the site administrator, maybe. Even with this decision there are many things to think about. What to do when there is no language specified in the url? Maybe the easy way, to assume an internal (from configuration or hardcoded) default language, or maybe a better user experience in order to determine the user’s culture from the browser’s request or even a nice solution that a friend of mine implemented: search in a database table the IP address from the request and determine the country and depending on the country, the page is displayed in that language. Finally the concrete strategy is up to you.

Whatever decision you take, it’ll be necessary to have small (or medium size) element usually on top right of the page, which is the language selector. This fellow is responsible for render the links to the entry point in other languages rather than the current one. If you have a fixed number of languages (which I do not recommend, unless your client pays too few for the project, don’t blame it, it’s a joke, don’t do it), there’s not much difficulty so it’s possible to implement a set of links with all the necessary dirty url construction.

But what if the languages amount varies, for example, they come from a database? Then the routing system is here for save the world. At this point I say the whole explanation about how to get these routes is out of the scope of this post, I’ll talk more on details in a dedicated post. (Seriously I promise I’ll do it!) Here are the route samples.

routes.MapRoute(
    "Default_ln", // Route name
    "{lang}/{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", 
        id = UrlParameter.Optional },  // Parameter defaults
    new { lang = "[a-z]{2}(-[A-Z]{2})?" }
);

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", 
        id = UrlParameter.Optional }  // Parameter defaults
);
    

Well, these routes really do not differ too much from the default template in Global.asax.cs at Visual Studio 2010. The order is a key point for the success and the new parameter introduced here is lang in the first route. If the url contains the language as in the second and third in the above urls, they will match the first route ("Default_ln") and if the url does not contain any information about language, then it’ll match the second route ("Default").

Note the regular expression (regex) in the first route as a constrain, I mean, the first segment is a language if and only if the segment content matches the regex, which in fact verifies the culture format (such as es-ES or en-GB, or just es or en) you are free to modify it and don’t be afraid of, the regex don’t bite.

The language selector is to be done in order to the crawler (and the human visitors too) be able to find the content written in other languages. The first (and easiest) solution maybe using static links pointing to the home page, followed by the language code or empty for the default. Really, don’t do that! What if the user has navigated deeper in the content tree? In this case, the user will have to navigate again through the path, and that’s not good. The link should point to the current content path but as child of target language. The routing system allows us to do this just setting properly the values for routeData parameter in any HTML extension method used in the views.

Assuming we have in our viewmodel a propery named Languages which is a list of some class with Code and Name properties. One first implementation could be as follows:

foreach (var lang in Model.Languages)
{
    @Html.ActionLink(lang.Name, null, new {lang = lang.Code})
    @Html.Raw("&nbsp;")
}
    

The result is acceptable but there’s a small glitch with url generation, the default language doesn't match with the initial definition about not explicitly show the language, it generates the lang parameter for all language even for the default one. What to do? Or better, why this come about? The origin of this is that we are saying, for each language in the list generate a link with the parameter lang equals this language’s code. We could instead to say, if this language is the default then do not set the parameter lang et c’est tout! As in this fragment:

foreach (var lang in Model.Languages)
{
    if (lang.Code == DefaultLangCode)
    {
        @Html.ActionLink(lang.Name, null, new { })
    }
    else
    {
        @Html.ActionLink(lang.Name, null, new { lang = lang.Code })
    }
    @Html.Raw("&nbsp;")
}
    

But that doesn’t work too, why? If we are in the default language (/) everything appears to be ok, but if we change for example to Spanish (/es) then checkout the link to our default (/es)! Surprise! And it should be just /. The reason is behind the scenes of routing system, it “fills” the route parameters with the current parameters explicitly passed as in lang, and falls back with the current request context data and in this case current request has the lang parameter that the explicit parameter did not pass, so finally the link is generated with the parameter lang equals the current lang. Only after to have understood this particular matter about the routing system we are able to fix the issue, as follows:

foreach (var lang in Model.Languages)
{
    if (lang.Code == DefaultLangCode)
    {
        var currentlang = ViewContext.RouteData.Values["lang"];
        ViewContext.RouteData.Values["lang"] = null;

        @Html.ActionLink(lang.Name, null, new {})

        ViewContext.RouteData.Values["lang"] = currentlang;
    }
    else
    {
       @Html.ActionLink(lang.Name, null, new {lang = lang.Code})
    }
    @Html.Raw("&nbsp;")
}
    

What’s the trick here? In this case we have said as part of the if condition for the default language, save the current value of route parameter lang in a temporary variable, then set to null (makes the same effect as remove it) without the lang garbage, generate the link and restore the value to the route data dictionary so the rest of the languages generate their link with this parameter which is necessary.

Sometime I comment with my developer friends and I say, I hate the web development but at the same time I love it! Because most of the time I have to be finding the exact trick for achieve the expected result and that’s the magic of software development!

Tuesday, 21 February 2012

jQuery.NeatUpload – Examples refactored

jQuery.NeatUpload – Release 0.4

I’ve been using the jquery plugin for neatupload and the bugs keep coming up, well, that’s the developer’s life. Catching bugs is an ability that every developer must have and more than that, do not shame on, but be proud of.
This time I’ve improved the error handling when the server send as response some no comprehensive, for instance, there is a limit set in web.config for the maximum file size to upload and when the client attempts to send a file bigger than the limit, the server replies with some bizarre response.
As part of the mechanism implemented, it expects the HTML response for parse it and determine what to do, I mean, send information to the client indicating whether the request failed or not. Sometimes the HTML sent by the server was impossible to read because of some mysterious JavaScript error “Access denied”. I had no time for digging deeper in this matter, so I try-catch it and just a little extra setup in order to be consequent and ready. The release 0.4 can be downloaded here.

jQuery.NeatUpload – Examples refactored

In order to prepare for launch a new release of NeatUpload including these JavaScript features I’ve been doing some refactoring in the samples I published a few months ago. The first thing I’ll do is to apologize with the WebForms people, because I’ve let them in the road with the examples, just the part 1. Now the updated versions have both implementations WebForms and MVC3. Of course these new versions also have applied the bugfix mentioned above.
There’s something new in the web.config files, this time they are prepared for either IIS6 or IIS7+ and highly commented (well, this is questionable and relative to anyone’s need) every setting needed for set up NeatUpload even clarifying the confusing and inconsistent size units that Microsoft has implemented in both versions of IIS, they are in bytes and Kilobytes respectively.
Before describe what’s in these examples, I want to alert you about something that I’ve been dealing with many times and that has been cause of mysterious error in production scenarios. There is a setting in web.config that indicates the maximum time that IIS can wait before it shuts down the thread and return time out error. This is under and it’s expressed in seconds, this is especially useful when the files to be uploaded are really big.

What’s in the examples?

  • Default values: Shows how to use the minimum setup code and use the default values.
  • Changed Add and Upload texts: Shows how to change the texts for the elements that add and/or upload items rather than the default internal texts.
  • Changed Add and Upload elements: Shows how to change the default link for add and/or upload element by custom elements like buttons.
  • Custom cancel elements. Part 1: Shows how to change the cancel element by creating a simple new element inline and binding it to the internal click event.
  • Custom cancel elements. Part 2: Shows how to change the cancel element by cloning a complex element and binding it to the internal click event.
  • Start Upload Automatically: Show how to start automatically the upload without using a queue and adding one by one. This example uses just add element.
  • Show Progress Bar: Shows how to use a more cute visual feedback by styling up a progress bar that indicates the progress and changes the color if an error occurs.
  • Validating Data: Shows how to intercept the action of send the file to the server by performing validations to the associated data.
  • Sending extra Data: Shows how to send associated data along with the file by serializing it as JSON and how to receive it properly on the server.
à la prochaine mes amis!

Sunday, 22 January 2012

Good practice for ASP.NET MVC Pager


When the data to be listed in a page becomes too long everybody agrees that it’s necessary to split the long flow into several small pieces, well that’s known in IT world as paging data, as you should know from day-to-day work in web applications. Every web technology gives us in some way the opportunity to do this without too much complexity. ASP.NET MVC is not an exception, after a quick Google-research I’ve found, of course since this problem is so common, tons of implementations, but the most relevant (at least in my modest opinion) was the one we can find at http://en.webdiyer.com/. There is another important implementation at https://github.com/martijnboland/MvcPaging that has also a NuGet package for ease the distribution. Almost all the implementations I found were inspired by ScottGu's PagedList idea.
I inspected many others but the general idea was in a way or another the same mentioned before over and over again. Finally I decided grab the first one and start using it as it comes out of the box. It was really easy to use: just make sure of your viewmodel has a IPagedList object, then specify the controller, action, pagination options, ajax options and html custom attributes.
Long story short, everything went good until I found a scenario where I needed a parameter combination that the author did not foresee. Wow! I really appreciate the amount of overloads made by the author, but in some way it was not enough for my scenario, so that’s Open Source magic. I downloaded the project and inspected it in a more detailed way. It really allowed the most common ways to make the pager but I needed at same time to specify controller, action, route data and ajax options for accomplish my task, after all I think this is not so uncommon scenario, I had a filter for my list and of course when I changed the current page the filter information must keep between round trips to the server.
The solution was actually simple, just make another overload in the Helper class and ready, but I wanted to dig deeper in the project structure and implementation and I discovered something I didn’t like too much (and it’s something I’ve seen in almost every projects in my research). The logic and view were strongly coupled. I am not a software philosopher but I like the good practices and the life had demonstrated to me that they are important. When I say strongly coupled I mean the same class is responsible of these two different tasks and concerns.
The relation between the classes is like this:
+-------------+    Render Pager    +--------------+
| PagerHelper |------------------->| PagerBuilder |
+-------------+                    +--------------+

The idea was to split that big class into two classes PagerModel and PagerView (obvious naming?) where the class PagerModel is responsible for all the logic involved such as the tedious calculations about page numbers, amount of pages, etc. model integrity validations using as transport a class PagerItem, this class holds data about each item to be shown in the pager but NOT how is to be shown, it’s only responsible for return a valid list of PagerItem. This separation of concerns is not just for to be compliant with the “holy bible” of design good practices, I’ve done this because I forecasted that in a short future it was going to be useful.
My refactoring looks like this:
+-------------+ Render Pager   +-----------+  Get Model +------------+
| PagerHelper |--------------->| PagerView |----------->| PagerModel |
+-------------+                +-----------+            +------------+

That future moment is arrived a few days ago, when I had to implement the same pager but this time with a different markup, actually just HTML and links and no ajax compatibility despite the fact I’m using unobtrusive from the default template. With this new distribution it was easy to me to create a new type of view, and why not, a little change of name, PagerView to AjaxPagerView and the new view named HtmlPagerView. It looks this way:
            Render         +---------------+  Get Model             
       +------------------>| AjaxPagerView +-----------------+        
       |                   +---------------+                 V        
+------+------+                                         +------------+
| PagerHelper |                                         | PagerModel |
+------+------+                                         +------------+
       |                   +---------------+                 ^        
       +------------------>| HtmlPagerView +-----------------+        
            Render         +---------------+   Get Model             

This is my vision of making a reusable design; in this case, instead of making a bunch of if-else or switch-case statements I apply a mixture between the Strategy and Decorator Design Pattern where every kind of view is a different “strategy” of rendering and “decorates” the model, which allows me in a future to implement many other types of view without affecting the core functionality and the actual logic: the model. The input options must be processed by the model class and make all the proper decisions returning a data structure which in most cases is named view model, ready for the view engine to read the necessary data from it. The view engine could be dependent in some way of the model element, but the model can NEVER be dependent of the view engine.
I hope this little refactor-reflection had made you think a bit more about real code reuse and the importance of using good practices and design patterns not just for to follow magic guidelines. I’d like to remark the consequences of developing software without keeping on eyes these techniques.
By the way, tell me about my ASCII-UML? Not bad, is it?

Thursday, 12 January 2012

Extending Unobtrusive AJAX behavior

One of the nice features that come with ASP.NET MVC 3.0 with no doubts is the addition of scripts for unobtrusive behavior regarding AJAX and validations. In this case I’ll refer to the AJAX mechanism using this technique. It allows you to write the least JavaScript code and achieve the partial update in a web page and it has a big plus, if JavaScript is disabled in the browser (or any other reason that prevents the js execution), no problem, everything continues working just without partial updates.
There are many scenarios where this is good enough for us and that’s all, write the server side code in the controller and the appropriate Html helpers using @Ajax setting up the target Id element to update after the remote call, maybe the “loading” element or even a confirm dialog in order to prevent unwanted post such as delete elements. The most classical example of this is the typical administration backend for any website where we have a list with a pager element at bottom (usually a table) and a form in another page with the details for edit the values.
Now, if you wish to make something a little different than previous example, the troubles start coming up. Imagine this simple scenario, a form with several fields ready to accomplish whatever task, if the operation succeeds then a partial update is performed below the form with more data to be entered and if the operation doesn’t succeed then another partial update is performed above the form showing the server errors. After this brief a little messy, the point is: there are more than one target id elements to update and only in the server this decision in taken; we don’t know how to specify the target id just declaring the Html helper.
My solution for this issue: conventions to the rescue!  I’ve made my own convention in this case. There is a script that is responsible of receiving all AJAX requests and inspects the content looking for the concrete target id and then it puts the content within the correct target id. I explain in detail, every partial view must have a hidden field with id = partialviewid and the value is the target id to be updated in the client. This solves the issue because we can have n partial views, each one referring to a different target, so in the controller it’s possible to do any sort of if-else statements and return the appropriate partial view in every case.
Let’s talk about the script that parses the content, it consists in a function that resides in a js file as any other and that is included by layout page after all unobtrusive formal scripts. It looks like this:
function receiveAjaxData(data) {

    var tempdiv = $("div[id=temporary-div-ajax]");
    if (!tempdiv.length) {
        $(document.body).append("<div id='temporary-div-ajax' style='display:none'></div>");
        tempdiv = $("div[id=temporary-div-ajax]");
    }

Here I ensure the temporary-div-ajax exists and is a body child, this is the place where the content that arrives from the server is put.
    tempdiv.html(data.responseText);
    var hidden = $("input[type=hidden][id=partialviewid]", tempdiv);
    var loadfunc = hidden.attr("data-function-load");

Then I find the hidden previously mentioned and if I had defined a function to execute is also grabbed here.
    if (hidden.length) {
        // Remove the hidden after to have taken its value
        var pvid = hidden.val();
        hidden.remove();

        // Place the content into the real target
        var destiny = $("#" + pvid);
        destiny.empty();
        destiny.append(tempdiv.children());
      
        // Re-parse the destiny node, in order to the validator work properly
        $.validator.unobtrusive.parse(destiny);

        // if function exists then evalute it
        if (loadfunc) {
            eval(loadfunc + "();");
        }
        return false;
    }
    return true;

If the hidden exists then proceed to place the content at real destiny, as you could have seen there is also the possibility of to specify the name of a function to be executed when the partial view is placed into the target, this is useful when we want to execute startup view-specific logic. One thing important here is the return value, if the result is true that means the jquery.unobtrusive engine continues as usually and if false then it stops and no more internal steps are executed.
How to use it? This question becomes usual, eh?
Include this script after all jquery.unobtrusive specific preferably in layout page.
In every partial view include:
<input id="partialviewid" type="hidden" name="partialviewid" value="target-id" />

In every Ajax action link or form, specify the AjaxOptions parameter
@Ajax.ActionLink("Create", "Create", null,
    new AjaxOptions { OnComplete = "receiveAjaxData"}
)

I hope this simple example to be useful for your day-to-day work without too much headache, till the next!

Friday, 30 December 2011

NeatUpload jQuery plugin – Examples – Part 3

In my last post I covered three scenarios where we changed the cancel the link element and start upload immediately. Well, let's continue tweaking, in this case the turn is for the user experience, I’ll show how to display a fancy progress bar while the upload operation is in progress, validate elements before send the file and even send extra data attached to the uploaded file. Let’s start.

Scenario 5 – Showing a fancy progress bar.

In all previous examples I have shown a simple number followed by a “%” symbol to indicate the progress, but I real life the user experience should be more than that, so all we are accustomed to is to see a progress bar increasing its size horizontally until the maximum width is reached, or tell me if I am crazy!? At least Graphical User Interfaces have used this pattern for years and it works. So if we intercept the moment when the file is added to the queue, it’s possible take the control and to construct everything necessary for display the progress. Let’s check the code:
<link href="@Url.Content("~/Content/progress.css")" rel="stylesheet" type="text/css" />

fnShowStatus: function (plugin, index, data) {
    $('table[id=tablequeue] > tbody > tr[data-neatupload-rowprog=' + index + '] div.progress-bar').width(data.PercentComplete + "%");
},
fnAddFile: function (plugin, filename, form, index) {
    var cancel = plugin.options.createCancelLink(plugin, index);
    var row1 = $("<tr data-neatupload-rowname='" + index + "' class='uploadItem-uploading'></tr>");
    var row2 = $("<tr data-neatupload-rowprog='" + index + "' class='uploadItem-uploading'></tr>");
    $('table[id=tablequeue] > tbody')
        .append(row1).append(row2);
    row1.append($("<td style='width: 80%'></td>")
        .append("<div class='uploading-video-name'>" + name + "</div>")
        .append("<div class='uploading-video-file-name'>" + filename + "</div>"))
    .append($("<td></td>"));
    row2.append($("<td></td>")
        .append($("<div class='barcontainer'></div>")
        .append("<div style='width: 0%' class='progress-bar'>")))
    .append($("<td class='cancel'></td>").append(cancel));
},
fnRemoveFile: function (plugin, index, reason, html) {
    var row1 = $('table[id=tablequeue] > tbody > tr[data-neatupload-rowname=' + index + ']');
    var row2 = $('table[id=tablequeue] > tbody > tr[data-neatupload-rowprog=' + index + ']');
    if (reason == "canceled") {
        row1.removeClass("uploadItem-uploading").addClass("uploadItem-canceled");
        row2.removeClass("uploadItem-uploading").addClass("uploadItem-canceled");
        $('div.progress-bar', row2).width("100%");
    }
    $("td.cancel", row2).html("<span>" + reason + "</span>");
}
<div>
    <table width="100%" class="uploadItem" id="tablequeue">
        <tbody>
        </tbody>
    </table>
</div>

The first this I remark here is the css inclusion, of course for achieve nice things it’s necessary a good inspiration, which I don’t have, I confess it, but something not so ugly it’s done with the css provided in the example, as usually you’re free to play with it.
Here is the same function we’ve overridden in last scenario, fnAddFile, which is executed right after the user clicks the button Add. The main idea with that amount of code is create tow table row for each file in the queue, the first for show the file name and the second the progress and the cancel element, previously discussed. Please note, we have used the internal function to create the cancel element whatever to be its implementation (overridden or default).
The function fnShowStatus this time with a little jquery magic finds the progress element and updates its width instead of write directly the percent value. Finally the function fnRemoveFile ad you can guess is responsible of remove the rows involved with the file to be removed, as an apart the parameters for this function: plugin is a reference to the plugin as usually, index is the identifier related to the current file in the queue, reason is a string indicating the reason of removing the current file (canceled or completed) and the html parameter give us the data returned by the server after finished the work. In this case we have checked if the reason is canceled then fill the width and a different color in the progress bar for tell to the user that that upload did not success.
At the end of the example we find a div with a table inside and this table has an id = tablequeue and an empty tbody, this is the placeholder for the rows created in runtime by the code previously explained.

Scenario 6 – Validating data before to perform the upload.

Sometimes we have a form with some data and the upload can be performed only if the form is consistent with some rules and even attach some data, but I let this for the next scenario. For verify these rules I understand (and I think you too) to validate the input fields. Surprisingly I’ve anticipated this kind of behavior and there is a function that may be overridden whose name is fnValidate and receives a plugin object reference as parameter. Inside this function body you are able to use any validation engine such as jquery.validate or whatever you want, for didactic purposes I just made a very simple validation.
(...)
fnValidate: function (plugin) {
    var valid = $("#name").val() && $("#age").val();
    if (!valid) alert("Incorrect Data!");
    return valid;
}
(...)
<div>
    <label for="name">Name</label>
    <input id="name" name="name" type="text" value="" />
</div>
<div>
    <label for="age">Age</label>
    <input id="age" name="age" type="text" value="" />
</div>

As you can see, all I’ve done is test if the value of the name and age fields are not empty, in case of at least one of them is empty an alert box is shown. The rest of the plugin expects if you override this function to return true if everything is ok and false if there is something wrong with the input data.

Scenario 7 – Start upload immediately.

Sometimes we have to send some data to the server attached to the file, for example metadata associated to the file being uploaded, for solve this issue we can make a little trick in the fnAddFile function before send the data. We can gather the data and helping with the JSON object which is capable of serialize any JavaScript object into a string, and then that string is added to the form that actually send to file to the server. Remember that each file sent to the server is an actual POST with an actual form. In this case that form is received by parameter and it’s simply to create a new element, the ideal form field is the hidden field for this task and that’s what I do in the following code.
fnAddFile: function (plugin, filename, form, index) {
    var name = $("input[id=name]").val();
    var age = $("input[id=age]").val();
    $("input[id=name]").val("");
    $("input[id=age]").val("");
    var data = JSON.stringify({ name: name, age: age });
    $("<input type='hidden' name='filedata' value='" + data + "' />")
         .appendTo(form);
},
fnRemoveFile: function (plugin, index, reason, html) {
    alert(html);
}

@Html.Hidden("upload-action", Url.Action("UploadFileExtraData"))

The function fnRemoveFile that we used in the previous scenario, this time just show up with an alert box the html parameter, with the data returned by the server in the controller action that receives the post with the files. Please note here that I show the hidden field which saves that action, and note that is different than the previous scenarios, this time there’s something to do also in server side.
[HttpPost]
public ActionResult UploadFileExtraData(FormCollection collection)
{
    var tempPath = Server.MapPath("~/_temp_upload/");
    var value = string.Empty;
    for (var i = 0; i < UploadModule.Files.Count; i++)
    {
        value = UploadModule.Files[i].FileName;
        UploadModule.Files[i].SaveAs(tempPath + value);
        var data = collection["filedata"];
        var serializer = new JavaScriptSerializer();
        var deserializeObject = (Dictionary<string, object>)serializer.DeserializeObject(data);
        var name = (string)deserializeObject["name"];
        var age = (string)deserializeObject["age"];
        value = "Name = " + name + ", Age = " + age;
    }
    return Content(value);
}
I just show the controller action code (sorry webforms people, but don’t worry it’s the same in essence), this time there is a bit more of code in server side than previously. First thing new is to get from the collection, well it’s the same that take it from Request.Form[“…”], the important thing here is that we follow a convention the name filedata must match with the name we gave to the hidden field we created on the fly in fnAddFile and that’s why I marked in yellow background. The rest is simply deseralize it with the .NET powerful tools for that and finally store in the variable value the demonstrative string with the values extracted from the metadata and returned to the client.
Well, I think it’s all for the moment regarding the jquery.neatupload plugin. I hope this information to be useful for you. Any comment, feedback or even suggestion for improve it will be welcome. I’ll come back with some ASP.NET MVC 3 tricky features soon.
So Happy New Year to every one!

Friday, 16 December 2011

NeatUpload jQuery plugin – Examples – Part 2

In my last post I covered two scenarios where we changed the texts and the elements for the actions add and upload. Well, let's continue with these changes, in this case the turn is for the link of cancel operation. It's a bit more complex than the others, that's why I've let for another post, but no so hard to do.
Scenario 3 – Changing the cancel link.

Due to the fact the cancel link has a special function and is intended for call an internal function, it’s required that the custom cancel element to call sendCancel function on its click event. This function can be accessed through plugin parameter and options object. Let’s check the code:

@{
    // get the text from wherever i.e. some i18n service in the application
    var textAdd = "Add a file to upload list";
    var textUpload = "Start Upload";
    var textCancel = "Abort Operation";
}
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.neatupload.js")" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
    $(function() {
        $("#file1").neatupload({
            postDataUrl: $("input[type=hidden][id=upload-action]").val(),
            fnShowStatus: function (plugin, index, data) {
                $('span#progress-file').text(data.PercentComplete + "%");
            },
            textCancel: "@textCancel",
            selectorButtonAdd: "input[name=addfile]",
            selectorButtonUpload: "input[name=uploadfile]",
            createCancelLink: function (plugin, index) {
                var cancel = $('<div>' + plugin.options.textCancel + '</div>')
                        .click(function () {
                                                plugin.options.sendCancel(plugin, index);
                        });
                return cancel;
            }
        });
    });
</script>

@using(Html.BeginForm("UploadFile", "Home"))
{
    @Html.Hidden("upload-action", Url.Action("UploadFile"))
    <div>
        @Html.Label("newfield", "Select File: ")
        <div id="file1">
            place holder for the input -> file for upload
        </div>
        <input type="button" name="addfile" value="@textAdd" />
        <input type="button" name="uploadfile" value="@textUpload" />
    </div>
    <div>
        <span id="progress-file"></span>
    </div>
    <div>
        <input type="submit" value="save"/>
    </div>
}
Here is a new parameter introduced in the last release: createCancelLink, which corresponds to a function with 2 parameters: plugin and index.
·         plugin is a reference to the current plugin element and is used for access the functions with the current data.
·         index is the unique identifier for the current file being queued for upload.
In the example just created a “div” element with a custom text and set the click event to an anonymous function which calls to plugin.options.sendCancel(plugin, index); and that’s the key point, through plugin.options it’s possible access to functions declared as public in the plugin (as in any other jquery plugin). The current values of plugin and index are passed to sendCancel internal who is responsible for send a “cancel” message to the server and stops the internal frame (in case of upload is in progress).

Scenario 3.1 – Changing the cancel link using a more complex DOM element.
In the previous example I demonstrated how to change the element cancel, and that works will if this element is very simple (as in the example, of course), but what if we have an element previously created in the page? I suggest this code fragment for solve it.

(...)
createCancelLink: function (plugin, index) {
    var cancel = $("input[name=cancelupload]").clone();
    cancel.show().click(function () {
        plugin.options.sendCancel(plugin, index);
    });
    return cancel;
}
(...)
<input type="button" name="cancelupload" value="@textCancel" style="display: none" />

Here I have an input button named “cancelupload” hidden by default using inline style and this will be the element chosen for cancel. The first is get it via query (remember, we are using jquery so take all advantages) and make a clone, then show it and finally assign the click function for the event handler like the previous example.
Scenario 4 – Start upload immediately.
Sometimes we don’t want the user follow the two steps: add and upload, This is useful for applications where the user only upload one file at time, for example: attach a file in a webmail interface, set up a profile logo image, etc. I have a solution for that and I show you as follows:

fnAddFile: function (plugin, filename, form, index) {
    $(plugin.options.selectorButtonUpload).click();
}

I introduce you a new parameter fnAddFile, this is a function that is called when a new file is going to be added to the queue. By default this function renders a visual element where we can see the cancel element, the name of the file being queued and a placeholder for the progress element.

In this case I have overridden this default behavior and I just call the click event of upload button element using the plugin.options.selectorButtonUpload parameter previously explained, I know that could be called as a little dirty but I think is valid, if we already have defined a button and its click event with a lot of work done, why not call it and go? At least this is my concept of reuse of code.

Well, I think it’s all for today, in the next post I’ll talk the third group of scenarios for use this plugin, which include personalizing the user interface using a more cute progress bar and more use of the uploaded file in server side. I hope this information to be useful for you. The source code for this example is available here.