Archive

Archive for the ‘AJAX’ Category

Populating Select Lists in ASP.NET MVC and jQuery

September 25, 2009 Comments off

I’ve been working the last bit to find the best way to create/populate select (option) lists using a mixture of ASP.NET MVC and jQuery.  What I’ve run into is that the “key” and “value” tags are not passed along when using Json(data).

Here’s what I’m trying to pull off in jQuery: building a simple select drop down list.

var dd_activities = “<select id=’dd_activities’>”;
var count = data.length;
for (var i = 0; i < count; i++) {
 dd_activities += “<option value='” + data[i].Key + “‘>” + data[i].Value + “</option>”;
}
dd_activities += “</select>”;

$(“#activities”).before(dd_activities);

Using some very basic key/value data:

[
 {“3″,”Text Value”},
 {“4″,”Another Text Value”},
 {“1″,”More boring values…”},
 {“2″,”Running out of values”},
 {“5″,”Last value…”}
]

Without any sort of name, I was at a loss on how to access the information, how to get it’s length, or anything.  FireBug was happy to order it up… but that didn’t help.
 
My first attempt was to use a custom object, but that just felt dirty—creating NEW objects simply to return Json data.
 
My second attempt matched the mentality of newing new anonymous Json objects and seemed to work like a champ:
 

[Authorize]

[CacheFilter(Duration = 20)]

public ActionResult GetActivitiesList()

{

    try

    {

        var results =

        _activityRepository

            .GetAll()

            .OrderBy(x => x.Target.Name).OrderBy(x => x.Name)

            .Select(x => new

                {

                    Key = x.Id.ToString(),

                    Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

                })

            .ToList();

 

        return Json(results);

    }

    catch (Exception ex)

    {

        return Json(ex.Message);

    }

}

 
Well, not beautiful, but returns a sexy Key/Value list that Json expects—and that populates our select list.
[
 {“Key”:”3″,”Value”:”Text Value”},
 {“Key”:”4″,”Value”:”Another Text Value”},
 {“Key”:”1″,”Value”:”More boring values…”},
 {“Key”:”2″,”Value”:”Running out of values”},
 {“Key”:”5″,”Value”:”Last value…”}
]
The next step was to get that out of the controller and into the data repository… pushing some of that logic back down to the database.
 

var criteria =

    Session.CreateCriteria<Activity>()

    .CreateAlias(“Target”, “Target”)

    .Add(Restrictions.Eq(“IsValid”, true))

    .AddOrder(Order.Asc(“Target.Name”))

    .AddOrder(Order.Asc(“Name”))

    .SetMaxResults(100);

 

var data = criteria.List<Activity>();

var result =

    data

        .Select(x => new

            {

                Key = x.Id.ToString(),

                Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

            })

        .ToList();

tx.Commit();

return result;

 
A bit of formatting, restrictions, push the ordering back to the database, and a tidy SQL statement is created.
 
The last touch is the return type.  Since we’re returning a “List” of anonymous types, the return type of GetActivitiesList() must be an IList.
 
That shrinks down my ActionResult to a single call.
 

try

 {

     return Json(_activityRepository.GetActivitiesList());

 }

 catch (Exception ex)

 {

     return Json(ex.Message);

 }

 
That works… and will work for now.  Though, I’ve marked it as a HACK in my code.  Why?  I’m honestly not sure yet.  Just a feeling.
Advertisements

Html.Grid Rendering as Plain Text?

September 23, 2009 1 comment

Notice: Stupid, stupid moment described ahead.  Proceed with caution.

I spent a good half hour trying to figure out why my MVCContrib Html.Grid<T> wasn’t rendering.  It wasn’t throwing an error, it was simply returning the HTML code as Plain Text.

  • The AutoMapper code looked good,
  • The Html.Grid<T> code looked good (it’d be templated off another page anyway and that page was working),
  • The view model code looked good.

So why was I being greeted with garble junk?

${Html.Grid(Model.Details) .Attributes(Id => “RoutineDetails”) .Columns(column => { column.For(c => this.Button(“EditDetail”).Value(“Edit”).Id(string.Format(“edit_{0}”, c.Id))).DoNotEncode(); column.For(c => c.Activity.Target.Name).Named(“Target Area”); column.For(c => c.Activity.Name).Named(“Activity”); column.For(c => c.Sets); column.For(c => c.Weight); column.For(c => c.Repetitions); column.For(c => c.Duration); })}

Html.Grid that is not… well, at least not properly.

Encoding issue? Maybe. Data issue? Perhaps.

No, the issue was typing too quick and not paying attention.

public ActionResult New()

 {

     var viewModel = BuildRoutineNewViewModel(new Routine());

     return View();

 }

Yeah, that’s the problem… right there.  I’d forgotten to pass the view model into the View.  Apparently the Html.Grid<T> helper simply panics if the model you’re reading from is empty or null—rather than throwing an error.

Oddly enough, this is one of those times I’d wish the screen would have lit up red.  Lessons learned.

Rendering the Web Equally on Mobile Devices

June 26, 2009 Comments off

I’ve been digging through the Interwebs for a while now and, I thought, had worked out all of the “kinks” of rendering on a mobile device—specifically iPhones.

The special ‘viewport’ meta tag means the world to iDevices.

meta name=“viewport” content=“width = device-width” />

I’m faced with a new challenge—the Palm Pre’s built-in web browser.  My shiny new phone is great, but it isn’t without glitches.

The first glitch I’ve found appears to be a DNS issue— http://myserver/web won’t resolve; however, http://123.45.67.89/web will.  It seems to be touchy.  Most of our webs work just fine, others don’t.  I haven’t narrowed it down to a single server or architecture as it seems to be a bit of everything.  Wonky.

The next glitch is more important—the rendering.  One of our tools is a simple form-based tool that looks great on the iPhone; however, renders partial screen and “garbles” when you move around the screen.

Palm Pre:

Garbled image

iTouch/iPhone:

I’ve also found that anything in an ASP.NET Update Panel (like those Select buttons) are unusable.  Other webs I’ve used (Bank of America, etc) use AJAX just fine, so I don’t think it’s that—probably a coding issue I need to dig into and resolve.

UPDATE: Explicitly adding “LoadScriptsBeforeUI=’true’” to the ASP.NET ScriptManager seems to help with this.. a little.

Anyone else worked specifically with the Pre devices and rendering?  I’d appreciate any meta tags or layout ideas that worked. ๐Ÿ™‚  The Pre isn’t a common device in our organization—yet.

Implementing IEPNGFix as a Reusable Control

January 30, 2009 4 comments

Even with IE 8.0 on the horizon, a great deal of our internal users are still using IE 5.5 and 6.0.  While, for the most part, our current coding techniques are unaffected, we did move to using PNG files quite a while ago and are faced with rendering issues as the target audience for a few of our produces expands.

To solve those issues, I’ve been using TwinHelix’s IE PNG Fix behavior with a great deal of success; however, I dislike keeping track of multiple files and references between projects.  It made more sense to make it a reusable control and include it in our shared architecture library.  When Angus releases a new implementation, then I only need to update the control and push out the updated libraries rather than touching HTML in each project.

Here’s how:

1. Download the latest version of IE PNG Fix from here.

2. Add the IEPngFix.htc, blank.gif, and IEPngFix_tilebg.js (if using 2.0 Alpha 3) into your project.  Mark all three files as Embedded Content.

3. Create a basic CSS file that can be added to pages and call the IEPngFix behavior.  Use the full path to the Web Resource (we’ll add those in the next step).  It’s sensitive to the namespace of your project.

img, div, .pngfix, input {

    behavior: url(‘<%=WebResource(“Resources.IEPngFix.htc”)%>’);

}

3. Modify the Properties/AssemblyInfo.cs file and add the approprate Web References.

[assembly: WebResource(“Resources.IEPngFix.css”, “text/css”,

       PerformSubstitution = true)]

[assembly: WebResource(“Resources.IEPngFix.htc”, “text/x-component”,

       PerformSubstitution = true)]

[assembly: WebResource(“Resources.IEPngFix_blank.gif”, “image/gif”)]

[assembly: WebResource(“Resources.IEPngFix_tilebg.js”, “text/javascript”)]

Notice that the HTC behavior file is an “x-component”.  For a full list of MIME references, check out the w3schools.com.  Also, perform substitution allows us to use dynamic calls of resources—within resources, such as in our CSS file.

4. Create a new class that inherits from CompositeControl.  This control will add the javascript and CSS references into our projects.  Override the OnPreRender method and populate the calling Page’s header with the links to our two files.

protected override void OnPreRender(EventArgs e)

{

       // Base Code: http://www.twinhelix.com/css/iepngfix/

       // Include JavaScript for tiled background support.

       string javascriptInclude =

              Page.ClientScript.GetWebResourceUrl(GetType(),

             “Resources.IEPngFix_tilebg.js”);

           

       var jsLink = new HtmlLink

              {

                     Href = javascriptInclude

              };

       jsLink.Attributes.Add(“type”, “text/javascript”);

       Page.Header.Controls.Add(jsLink);

           

       // Include Css file that calls HTC.

       string cssInclude =

              Page.ClientScript.GetWebResourceUrl(GetType(),

             “Resources.IEPngFix.css”);

           

       var cssLink = new HtmlLink

              {

                     Href = cssInclude

              };

       cssLink.Attributes.Add(“rel”, “stylesheet”);

       cssLink.Attributes.Add(“type”, “text/css”);

       Page.Header.Controls.Add(cssLink);

 

       base.OnPreRender(e);

}

That’s it.  Build and add the new control to your project.  You can then add a new forms page and drop the control into the page.  I prefer, however, to keep a “DefaultPage” and inherit my pages from it—add once, apply to all. ๐Ÿ™‚

protected void Page_Load(object sender, EventArgs e)

{

       Page.Controls.Add(new IEPngFix());

}

Here we can see the rendered control. The PNG has a transparent background and without IEPngFix shows up as a white box rather than seeing the black background of the page.  Works like a champ!

IEPngFix in Action

Thanks again to Angus Turnbull for this excellent behavior!

Tags: , , , ,

Using xUnit.net in ReSharper 4.1 and MVC

September 11, 2008 1 comment

Ben Taylor has saved us all a HUGE load of frustration by releasing a patched version of the xUnit.net installer and libraries that works with ReSharper 4.1.

There’s a final step, however, if you want it to work with the MVC Framework (this is for Preview 5).

The default xUnit.net MVC template package includes a 3rdParty directory for the xUnit.dll file.  The Test project also references that same library for the context of the tests.  To take advantage of Ben’s new 4.1’esque library, you need to update the 3rdParty file with his or you’ll be seeing red.

Steps:

1. Open your MVC Test project.

2. Remove (delete) the 3rdParty/xunit.dll.

3. Add an Existing File to the 3rdParty directory, pointing to the new library from Ben.

4. Under the Test project’s References, refresh the xunit reference and be sure it’s picking up the new file (the caution icon should disappear).

5. Run your tests in ReSharper and be very happy. ๐Ÿ™‚

Working MVC tests with xUnit and Ben's Patch.

VS2008 and .NET 3.5 SP1 Success

August 12, 2008 Comments off

Danger, danger!Well, I’m 1/4 now upgrading the VMs to SP1.  The “one” that worked is the one I least expected.

Machine 1:

A simple VM used for a basic web project.  C#, Web Developer Tools installed—not even joined to the network.  No “hotfixes” were installed, but I ran the tool anyway just to be sure.  It chugged for a while and then threw an exception.  Feeling daring, I went ahead and tried to upgrade to SP1 and it didn’t even detect Visual Studio or .NET 3.5.  Hah.

Machine 2:

A prototyping VM that I copy web apps onto to run and test—nothing major, just VS2008, C#, web test tools, etc.  This one did have SP1 beta on it that I was dinking with as well as various Silverlight tools.  The patch removal tool worked just fine.  After a reboot, the SP1 installation got about 20% complete then McAfee (mcshield.exe) threw about 70 exceptions all at once and flooded the task bar.  The system then BSOD’d and reboot.  I tried another couple times to install SP1 (I can’t disable McAfee, ePO prevents it) with no success.

Machine 3:

This VM provides a test system for our customers to connect to, evaluate applications, and such.  VS2008 and .NET 3.5 (no SP1 beta) was installed more for convenience than anything else.  The system isn’t in use for the next few weeks, so worth a shot on this one.  I didn’t run the patch removal tool (perhaps that was my mistake) on this workstation and proceeded with installing SP1.  About 80% through the installation, devenv.exe crashed and asked to be debugged—of course, when I tried to debug, it crashed.  Hah.

Machine 4:

This is the one that worked; however, it’s the oddest, most broken of the bunch.  It’s had SP1 beta on it, various MVC preview builds, Astoria, bunches of Silverlight tools as well as various libraries and code bunches I have for newsgroup and forum posts.  The patch removal tool found a bunch of stuff and remove it without any issues.  After the reboot, SP1 installed (took about 45 minutes) and the system reboot.

And it works…

It works!

Seriously… why?

I still have a few VMs left to dink with and plan to throw it on my development workstation later this week after I wrap up a few projects and have some down time (I had planned to rebuild the entire workstation anyway—so good opportunity).

I hope, after I find some basic installation method, to have time to dig in to the features…

Wrapping Up CrossBrowserUpdateProgress Into a Control

August 11, 2008 Comments off

Download the Source.

A few weeks ago, I wrote about the joys of trying to create a cross browser UpdateProgress panel (or more to the point, work around oddities with IE6 CSS).

The post was fine, and the method works quite well; however, it’s not easily reproducable in it’s current form.  A custom web control; however, would solve that in a snap.

In this custom control, I’ll:

  • Determine if it’s IE6 or not and apply the approprate CSS
  • Accomodate the glitch where DropDownLists shine through in IE6
  • Provide public properties for the AssociatedUpdatePanelId and the text to appear in the UpdateProgress

Later on, I’ll probably tweak this to simply make the ProgressTemplate a public property—just like a standard UpdatePanel; however, for now, this meets the needs—a basic update progress control.  Simple is good. ๐Ÿ™‚

Basic CBUP

On the ASPX side, the code usage is quite simple:

<ts:CrossBrowserUpdateProgress runat=”server” ID=”cbup”

AssociatedUpdatePanelID=”UpdatePanel1″
DialogText=”Please wait…” />

Behind the scenes, the code is pretty spartan.  The WebControl renders an UpdateProgress control, applies the DialogText and AssociatedUpdatePanelID properties, creates the ProgressTemplate with the IFrame (to fix IE6 drop down lists), modal background, and the dialog itself.  Let’s take a look at the code.

There are three methods that are overridden: OnPreRender (to set the CSS), RenderContents (to create the controls and set a final ZIndex for IE6), and the actual CreateChildControls.

OnPreRender

Thankfully, the Request object has a helpful HtmlBrowserSpecifications array that keeps track of properties such as the browser, versions, javascript compatibility, etc.  From this, we can determine our IE 6 users and provide the approprate CSS.

protected override void OnPreRender(System.EventArgs e)

{

if (this.Context.Request.Browser.Version == “6.0” &&

this.Context.Request.Browser.Browser == “IE”)

{

       var ie6Css =

Page.ClientScript.GetWebResourceUrl(GetType(), “ie6.css”);

var iis6CssLink = new HtmlLink { Href = ie6Css };

       iis6CssLink.Attributes.Add(“rel”, “stylesheet”);

       iis6CssLink.Attributes.Add(“type”, “text/css”);

       this.Page.Header.Controls.Add(iis6CssLink);

}

 

var generalCss =

Page.ClientScript.GetWebResourceUrl(GetType(), “general.css”);

var generalCssLink = new HtmlLink { Href = generalCss };

       generalCssLink.Attributes.Add(“rel”, “stylesheet”);

       generalCssLink.Attributes.Add(“type”, “text/css”);

       this.Page.Header.Controls.Add(generalCssLink);

 

       base.OnPreRender(e);

}

The CSS files are included as embedded resources (and should be approprately marked in the AssemblyInfo.cs) with the control.

RenderContents

RenderContents is nice and simple—set the ZIndex of the entire control, make sure that everything is in place, and render!

protected override void RenderContents(HtmlTextWriter output)

{

output.AddStyleAttribute(HtmlTextWriterStyle.ZIndex, “99999999”);

       EnsureChildControls();

       base.RenderContents(output);

}

Is the ZIndex necessary?  Quite frankly, I’m not sure.  For IE6, 3/5ish tests failed WITHOUT it—the drop down lists still shined through in spite of the IFrame.  Having it in there seemed to guarantee it working.  Your mileage may vary. ๐Ÿ™‚

CreateChildControls

The CreateChildControls method is responsible for generating the actual UpdateProgress control and adding it to the WebControl for rendering.

protected override void CreateChildControls()

{

base.Controls.Clear();

 

       if (!ChildControlsCreated)

       {

              var baseProgress = new UpdateProgress

             {

                     DisplayAfter = 100,

DynamicLayout = false,

AssociatedUpdatePanelID = AssociatedUpdatePanelID,

ProgressTemplate = new ProgressTemplate()

};

this.Controls.Add(baseProgress);

 

}

base.CreateChildControls();

}

Seems a bit to easy, huh?  It is.  Notice that the ProgressTemplate is creating a new ProgressTemplate?  ProgressTemplate is a Template (or ITemplate) and to dynamically assign it, I had the best luck creating an internal class to handle rendering the template—this is where the guts of the control actually fall.

ProgressTemplate

The only required method of an ITemplate is InstanciateIn(Control) and I’m more than happy to accomdate.

/// <summary>

/// Fake ProgressTemplate for the UpdatePanel.ProgressTemplate.

/// </summary>

internal class ProgressTemplate : ITemplate

{

public void InstantiateIn(Control container)

       {

// Create IFrame for IE6 “coverups” of drop down lists.

       if (HttpContext.Current.Request.Browser.Version == “6.0” &&

HttpContext.Current.Request.Browser.Browser == “IE”)

{

var iFrame =

new LiteralControl(@

<iframe id=’UpdateProgressHideSelect’>

</iframe>”);

container.Controls.Add(iFrame);

 

       }

       var progressBackground =

new LiteralControl(@

<div id=’UpdateProgressModalBackground’>

</div>”);

 

var progressDialog =

new LiteralControl(@

<div id=’UpdateProgressPanel’>

<div id=’UpdateProgressText’>” +

_dialogText +

“</div></div>”);

 

                container.Controls.Add(progressBackground);

                container.Controls.Add(progressDialog);

}

}

To access the _dialogText inside the internal ProgressTemplate class, you can either pass it as a variable when you create ProgressTemplate OR set your private field to static.

Put that all together and the output HTML is nice and tidy:

<span id=“cbup”>

<div id=“ctl03”

style=“z-index: 99999999; visibility: hidden; display: block;”>

<div id=“UpdateProgressModalBackground”/>

<div id=“UpdateProgressPanel”>

<div id=“UpdateProgressText”>Please wait…</div>

</div></div>

</span>

There’s still work to do, but it provides a nice base to toss in my controls library.