MVC Not the Magic Bullet

by Admin 1. July 2012 08:31

I have been working with ASP.MVC 3 fairly heavily for the past year and I am anxiously awaiting the production release of VS 11 and MVC 4.0.  I think ASP.MVC  is a fantastic platform and solves many of the issues that exist with ASP.Net webforms.  The issue that I have notice though is many people in the development community are touting it as a “Magic Bullet” of sorts.  I have heard “Development times will shrink when we move to MVC” or “This would be so much easier in MVC” or “You won’t have to worry about page bloat in MVC.”  These comments are really only half truths.  

Will development time speed up under MVC?  In the long run with competent architects, developers and designers timelines should shrink a small amount (I need more data to give exact numbers) in MVC. Developers can spend their time writing business logic without having worry about the impact to the UI (with some considerations).  Designers can focus on making the UI look good without worrying about to much ASP gobbledygook (with some considerations). In addition SEO competent designers will have a much easier time adding SEO compliance to the site (if that is your goal).

Will development get easier in MVC? Yes and no.  I would like to discuss this particular topic in three parts. First, there are many seasoned ASP.NET Web Form developers out there that are well versed in the page life cycle, web controls and the ins and outs of ASP.NET in general, and can deliver excellent web sites working in that framework.  MVC (razor in particular) will be a complete paradigm shift for them.  I have heard several developers compare it to classic ASP and they are a bit annoyed they are being pushed back in that direction.  This could not be further from the truth, but a cursory glance at MVC (especially non-razor) it is easy to see how you could jump to that conclusion.  The removal of view-state and control-state presents a new set of challenges when working with pages.  The heavy dependency on JavaScript and JQuery on validations, AJAX and UI will be a bit of a learning curve for web developers that have only had to deal with that on a cursory level.  It is now, in my opinion, impossible to keep developers shielded from JavaScript and to a point even CSS.  Most developers are already comfortable in these areas but I know of several that only use the two when absolutely necessary.

Secondly, MVC (and HTML 5) blurs the lines between behavior, formatting and content which traditionally follows this model:

Web Block

The new model looks something like this:

Web Venn

Leading to questions of what should I use and when?  There really is no hard and fast answer to that question.  I usually use the following as a guide line in order of importance?  

Target Browser Compatible > Robustness of Functionality > Ease of Implementation > Maintainability

This wasn’t as much of a concern in ASP.NET Webforms as many of the web controls used handled all three aspects in their server side properties.  Which brings me to my third topic; the lack of standardized custom controls with ASP.NET MVC.  With ASP.NET MVC there is no such beast as a “Web Control”, there are only HTML helpers, JavaScript and JQuery libraries.  The big component players (Telerik, Infragistics and ComponentOne) are providing some JQuery libraries and MVC libraries but not much that competes with the free items already out there also JQuery changes so often that using version based component specific JavaScript and CSS really limits your ability to keep up to date.  I found out the hard way trying to go with the old model of “buy rather than build” can severely limit your options.  Recently I have been going the way of “find and tweak rather than build from scratch.”  GitHub and CodePlex are becoming the new source of third party components.  These controls however are purely an implementation of HTML, JavaScript/JQuery and CSS.  They are not server code specific.  So throw out the idea of setting some properties in the designer and it just working.

Lastly, can developers be completely oblivious to page bloat?  Absolutely not, page bloat has just shifted from viewstate to JavaScript includes and CSS.  Finding all of the controls to replace existing libraries comes with the price of including more and more .JS files.  So if you think you are trading you 500k viewstate for 0k MVC, guess again.  If you are not careful it could be 500k viewstate for 1 meg of added script.  Luckily MVC 4 is working on combatting that issue with bundling, but that isn’t a magic bullet either.

The long and short; if you were slashing timelines and removing servers from you web farms because you thought all of your problems were solved.  You are gonna find yourself up “bit” creek without a paddle.

 

Tags: , , ,

ASP.NET | CodePlex | GitHub | HTML5 | MVC3

Dynamic Data: Skeptic Turned Believer

by Admin 9. April 2012 12:35

I have to admit for the most part I loathe code generation tools.  The code generated is, in most cases, unsupportable, messy, uncommented and not optimized.  But that is the nature of code generators (otherwise most of us wouldn’t have jobs).  Recently I wrote an application that requires an administration piece for some of our database administrators.  Being technical people they do not need all of the bells and whistles of your average user.  I normally try to avoid these types of applications; they are not sexy, tedious and consume more time to develop then it appears they should.  

I had heard of Dynamic Data Web sites about 3 years ago and dismissed them as another code generation nightmare, however, in preparing for my Microsoft Web exam I ran across them again. I realized they are not code generated web sites, they are, in fact, a template with data hookups allowing developers to create a quick standard CRUD (Create, Read, Update and Delete) web site with a simple grid/detail page interface.  After looking into the details of how to implement, develop and configure the application I realized Dynamic Data is a perfect candidate for quickly implementing the application development task I had at hand.

There is a simple checklist I came up with to determine if an application is a good candidate for an out of the box (mostly) dynamic data implementation:

1.Are a relatively low number of users going to be accessing the application?

2.Can the application be created with a relatively simple UI

3.Is the application used for mainly administration (user creation/modification, updating type tables, updating contacts, etc.?

4.Is this not a user facing application?

5.There are no business requirements for the application

If the answers to all of those questions are yes, there is no reason not to create a dynamic data web site.  I would go into the details of how to create a Dynamic Data Website but Visual Studio 2010 makes it so easy I would just be regurgitating the steps provided for you.  I will say this, give it a try with one of your existing databases and you will see just how easy it is to create a fully functional application in minutes.

Tags: , ,

ASP.NET | Entity Framework | Dynamic Data

MVC Makes AJAX easier

by Admin 12. February 2012 19:07

MVC is a pretty new paridigm to me, I just started using it about 5 months ago, but one of the first things I noticed is how much easier it has made AJAX.  This is coming from someone who has had a very long career in ASP.NET.  There were a few different ways to provide Ajax functionality in ASP.NET the evil update panel being the easiest to implement.  My preference and, IMO, the more correct approach was to use the AJAX framework in conjunction with AJAX Aware WCF/Web Services.  The low framework overhead (no Eventing Model) in conjuction with the relatively small request/response package made these fairly easy to implement and perform very well.  The problem with these services is they were still tied up in all sorts of framework gook.

With MVC, all of that framework gook is gone, it is a much simpler PHP style implementation of AJAX.  There are several ways to utilize AJAX in the MVC world, there are the AJAX MVC Helper Class which is very easy to work with, but I perfer a pure JQuery ajax approach.

Enough talk here is an example of a simple implementation of ajax using 4 commonly used methods:

First the Controller (in this case I am using the Products table of the Northwind Database (kickin' it old school)):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
namespace JqueryAjax.Controllers
{
    public class ProductsController : Controller
    {
        //
        // GET: /Products/
 
        public ActionResult Index()
        {
 
            List<Product> prodList = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prodList = ctx.Products.OrderBy(p => p.ProductName).ToList();
 
            }
            return View(prodList);
        }
 
        public ActionResult _productInfoJSON(int? id)
        {
            Product prod = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == id);
 
            }
            return Json(prod, JsonRequestBehavior.AllowGet);
        }
 
        public ActionResult _productInfo(int? id)
        {
            Product prod = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == id);
 
            }
            return PartialView(prod);
        }
 
        [HttpPost]
        public ActionResult _productInfoJSONParams()
        {
            Product prod = null;
            int prodId = int.Parse(this.ValueProvider.GetValue("id").AttemptedValue);
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == prodId);
 
            }
            return Json(new { prod.ProductName, prod.UnitPrice });
        }
 
    }
}

I use the "_" syntax to denote partial actions and views.  So looking at the above code you will notice there is only one full action "Index", so lets look at its view:

@model IEnumerable<JqueryAjax.Product>
 
@{
    ViewBag.Title = "Products List";
}
 
@section script{
    <script src="@Url.Content("~/Scripts/Info.js")" type="text/javascript"></script>
}
<h2>Index</h2>
<table>
    <tr>
        <th>
 
        </th>
        <th>
            ProductName
        </th>
    </tr>
 
@foreach (var item in Model) {
    <tr>
        <td>
            <a class="prodInfo" href="#" data-product-id="@item.ProductID">
                <img src="../../Content/Images/info.jpg" width="20" height="20" alt="info" border="0" />
            </a>
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProductName)
            <div id="product-@item.ProductID" style="display:none;">
            </div>
        </td>
    </tr>
}
 
</table>
So in this view I am simply building a Table of product names with an info image, easy peasy.  The Ajax parts of the html are housed in the:
 
<div id="product-@item.ProductID" style="display:none;">
And the:
<a class="prodInfo" href="#" data-product-id="@item.ProductID">

The former is the place holder for our dynamic content and the latter is the link to our dynamic content.  Now that we have all of the page scaffolding in place we need to hook up the pieces.  There are several ways we can retrive the content.  We could retrieve a standard JSON object from a controller _productInfoJSON and _productInfoJSONParams or you can return a partial view.  This is where the power of MVC really hits home.  You can craft a fully functional page and return it to your AJAX container.  That is pretty sweet...  But first lets look at the JSON example:

I created 2 a JSON Get (useful for RESTful services) and a JSON Post (prefered for internal web site calls):

Here is the Java script for calling the JSON get in conjuntion with the previously crafted view and controller:

/// <reference path="jquery-1.7.1.min.js" />
$(document).ready(function () {
    $(".prodInfo").click(function (e) {
        //stop the href="#" from firing
        e.preventDefault();
 
        var prodId = $(this).data("productId");
        jsonGet(prodId);
 
    });
});

function jsonGet(prodId) {
    $.ajax({
        url: "/Products/_productInfoJSON/" + prodId,
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html("<span> price:"+ data.UnitPrice +"</span>");
        }
    });
}
and the JSON parameterized post:

jsonPost(prodId);

function jsonPost(prodId) {
    $.ajax({
        url: "/Products/_productInfoJSONParams",
        type: "POST",
        data: { id: prodId },
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html("<span> price:" + data.UnitPrice + "</span>");
        }
    });
}

This will get you a simple return value that you can format in JQuery.

Pretty simple right?  Well its about to get easier.  Now lets say we want to return a significant amount of data to the client and we don't want to do that messy JavaScript HTML formatting.  Partial Views to the rescue.  Create the following partial view from the _productInfo action:

@model JqueryAjax.Product
 
<fieldset>
    <legend>Product Info</legend>
 
    <div class="display-label"></div>
    <div class="display-field">
        QuantityPerUnit: @Html.DisplayFor(model => model.QuantityPerUnit)
    </div>
 
    <div class="display-field">
        UnitPrice: @Html.DisplayFor(model => model.UnitPrice)
    </div>
 
    <div class="display-field">
        UnitsInStock: @Html.DisplayFor(model => model.UnitsInStock)
    </div>
 
    <div class="display-field">
        UnitsOnOrder: @Html.DisplayFor(model => model.UnitsOnOrder)
    </div>
 
    <div class="display-field">
        ReorderLevel: @Html.DisplayFor(model => model.ReorderLevel)
    </div>
 
    <div class="display-field">
        Discontinued: @Html.DisplayFor(model => model.Discontinued)
    </div>
</fieldset>

Now change the JS click event to fire:

partialJqueryGet(prodId);

with the function definition of:

function partialJqueryGet(prodId) {
    $.get("/Products/_productInfo/" + prodId,
    function (data) {
        $("#product-" + prodId).toggle();
        $("#product-" + prodId).html(data);
    });
}

BA BAM done.  Now you are returning a partial view from an ajax call.  You can also use a pure jquery ajax implementation as opposed to the Get helper class:

function partialAjaxGet(prodId) 
{
    $.ajax({
        url: "/Products/_productInfo/" + prodId,
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html(data);
        }
    });
 
}

 

All of the code and the northwind database can be found here:

JqueryAjax.zip (2.67 mb)

http://www.microsoft.com/download/en/details.aspx?id=23654

 

Tags: , , , , , ,

AJAX | ASP.NET | jquery | JSON | MVC3 | Razor

FAJAX Image Buttons

by Admin 17. November 2010 15:40

I had an interesting question the other day.  "How can I use AJAX to stream images back from a database to the web browser?"  The answer is, you dont need to. This functionality has been around since .net 1.0.  You can create an HTTP Handler.  Http Handlers give you control over any request recieved from the client.  In the case of an Image streamed from... whatever, you can do it quite simply...  Here is all of the code you need:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SlideShow.aspx.cs" Inherits="SlideShow" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Slide Show</title>
    <script>
        var index = 1;
        function getImage() {
            //increment counter
            if(index == 5){
                index = 1;
            }
            else{
                index ++
            }

            document.getElementById("sldImage").src = index + ".ipg";
        }
    </script>
</head>

<body>
    <form id="form1" runat="server">
    <div id="slidePanel">
        <img id="sldImage" src="1.ipg" alt="slideImg" />
    </div>
    <input type="button" value="Next" onclick="getImage();return false;" />
    </form>
</body>
</html>

In the code above I am I am using an "IPG" extension as a replacement for jpegs.  This code will also support gif as "IIF".  The Image Handler would look as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
/// <summary>
/// Summary description for Class1
/// </summary>
public class HttpImageHandler : IHttpHandler
{
    public void ProcessRequest(System.Web.HttpContext context)
    {
        long fileID = 0;
        long.TryParse(Path.GetFileNameWithoutExtension(context.Request.Path), out fileID);

        context.Response.ContentType = getContentType(context.Request.Path);
        FileInfo fi = null;
        switch (fileID)
        {
            case 1:
                fi = new FileInfo("C:\\Pics\\Chrysanthemum.jpg");
                break;
            case 2:
                fi = new FileInfo("C:\\Pics\\Desert.jpg");
                break;
            case 3:
                fi = new FileInfo("C:\\Pics\\Hydrangeas.jpg");
                break;
            case 4:
                fi = new FileInfo("C:\\Pics\\Jellyfish.jpg");
                break;
            case 5:
                fi = new FileInfo("C:\\Pics\\Koala.jpg");
                break;
        }
        context.Response.BinaryWrite(getImage(fi.OpenRead(), Path.GetExtension(context.Request.Path)));
        
        context.Response.End();
    }
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    /// <summary>
    /// Gets the image steram as a byte array
    /// </summary>
    /// <param name="path">The </param>
    /// <returns></returns>
    private byte[] getImage(Stream imageData, string ImageType)
    {
        Bitmap imgIn = new Bitmap(imageData);
        System.IO.MemoryStream outStream = new System.IO.MemoryStream();

        imgIn.Save(outStream, getImageFormat(ImageType));

        return outStream.ToArray();
    }
    private string getContentType(String path)
    {
        switch (Path.GetExtension(path))
        {
            case ".ipg": return "Image/jpeg";
            case ".iif": return "Image/gif";
            default: break;
        }
        return "";
    }
    private ImageFormat getImageFormat(String ImageType)
    {
        switch (ImageType)
        {
            case ".ipg": return ImageFormat.Jpeg;
            case ".iif": return ImageFormat.Gif;

            default: break;
        }
        return ImageFormat.Jpeg;
    }
}

In this example I am just using the default images that ship with windows.  You will need to make a few changes to your web config, and if you are using IIS 6.0 or below, you will need to add the filter to your list of served content.

<!-- in system.web -->
    <httpHandlers>
      <add verb="*" path="*.ipg"
        type="HttpImageHandler"/>
      <add verb="*" path="*.iif"
        type="HttpImageHandler"/>
    </httpHandlers>
<!-- system.webServer -->
    <handlers>
      <add  verb="*" path="*.ipg"
            name="HttpImageHandler"
            type="HttpImageHandler"/>
      <add  verb="*" path="*.iif"
            name="HttpImageHandler"
            type="HttpImageHandler"/>        
    </handlers>

That is pretty much it...  pressing the next button will go to the server and retrieve the corresponding image file, however it is stored.

Tags: ,

ASP.NET

Calendar

<<  October 2017  >>
MoTuWeThFrSaSu
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar

Page List

RecentComments

None