ADO.NET Data Services

I’m really impressed with what is happening around the ADO.NET Services (aka Astoria).

Think ‘RESTful’ url queries to entities in a way to abstracts out the particular underlying IQueryable provider.

This really does create a technology (as in Entity Framework vs. L2S vs. NHibernate.Linq) agnostic layer.

From the link above – a good set of video’s to watch (short and to the point):

How Do I …

More on Querying:  (how client queries relate back to the ADO.NET Services protocol RESTful queries)

ADO.NET Data Services – Querying with LINQ by Mike Taulty (and this link will show his other screencasts)

Further Reading:

Lost in Tangent has a series of Training blog posts

I do see ADO.NET Data Services as a great fit to behave as the service layer to your underlying domain entities model.

One thing that Mike Flasko demonstrates in the video (and Mike Taulty’s video) is the ability to query using several approaches…

I have two here:

      var entities = new BistroEntities(new Uri("http://localhost:56987/BistroWebDataServices.svc"));
      var query = from c in entities.Companies
                  where c.CompanyID.Equals(new Guid("56e0d889-5f54-4e2d-805b-9ba700e6b9e4"))
                  select c;
      var company = query.SingleOrDefault();
      company.Note = "Updated on " + DateTime.Now;
      entities.UpdateObject(company);
      entities.SaveChanges();

      DataServiceContext context = new BistroEntities(new Uri("http://localhost:56987/BistroWebDataServices.svc"));
      context.IgnoreMissingProperties = true;
      var q = context.Execute<Companies>(new Uri("/Companies", UriKind.Relative));
      var testCo = (from c in q
                    where c.CompanyID.Equals(new Guid("56e0d889-5f54-4e2d-805b-9ba700e6b9e4"))
                    select c).SingleOrDefault();
      testCo.Note = "Updated on " + DateTime.Now;
      context.UpdateObject(testCo);
      context.SaveChanges();
 

It is interesting to see the result of the ‘var’ query above:

{http://localhost:56987/BistroWebDataServices.svc/Companies(guid'56e0d889-5f54-4e2d-805b-9ba700e6b9e4')}
 

It is possible to drill down further, ie. to get all the contacts at a company assuming a 1 to many relationship:

{http://localhost:56987/BistroWebDataServices.svc/Companies(guid'56e0d889-5f54-4e2d-805b-9ba700e6b9e4')/Contacts}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

You can make RESTful Uri queries, just as example of two:

http://localhost:56987/BistroWebDataServices.svc/Companies?$filter=startswith(Name,%20%27Test%27)
http://localhost:56987/BistroWebDataServices.svc/Companies?$orderby=Name
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The first one queries the underlying Company entity object (which is mapped to the Companies table) and does a startswith query on the property of ‘Name’.

The second query does an orderby query by Company name.

Cool stuff  🙂

(It’s no surprise that a decision was made by the RIA.NET Domain Services team to use ADO.NET DataServices as it’s underlying protocol).

For those with a close eye to detail, note the ‘unit of work’ with the ability to send the ‘UpdateObject’ – there is also the ability to send changes back with a batch update:

ie. 

entities.SaveChanges(SaveChangesOptions.Batch);
 

For an advanced topic, check out using ‘Modeling Data for Efficient Access at Scale’ w/Azure & ADO.NET DataServices – good video !

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Advertisements

jqModal Tips – ajax dynamic dialogs

I’ve been using jqModal to handle all my dialog ‘window’ forms on a current application.  I’m not going to get into all the details here, but rather expand on a few complex operations.

First, one powerful aspect of jqModal is the ability to assign a dialog based on a href trigger link.

Here is an example of what this means:

$(‘.dialogs’).jqm({ajax:’@href’,modal:true, trigger: ‘a.triggerLink’});

ajax

If passed, dialog contents will be loaded remotely via ajax. You can pass the URL (e.g. $.jqm({ajax:’remote/dialog.html’}) or extract it from an attribute of the triggering element. For instance, $(.jqm({ajax:’@href’}) would grab contents from bar.html if the triggering element was <a href=”foo/bar.html”>Open Dialog</a>. If a more complicated loading routine is desired, the onShow() callback should be leveraged.

So, let’s say you have the above as described where you want to open a dialog for a list of items : the above dialog contains the very important trigger reference that is saying ‘any a href with class ‘triggerLink’ will fire an event to open the dialog.

Then, the added functionality is ‘when this happens, it’s going to call to the href of that trigger to determine the ajax form to load.

Let’s say I have a html form that I want in the dialog.  The href will need to point to that html…. ie.  myform.html.   I could just do the following:

$('.dialogs').jqm({ajax:'myform.html',modal:true, trigger: 'a.triggerLink'});

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

When the trigger link is clicked ie. a href=”#” class=”triggerLink”  (brackets removed) it will open a dialog with the myform.html as it’s content.

This works particularly well with something like asp.net mvc.  ie. my system is to use a ascx (a snippet of html basically) that is loaded by calling a controller action.   Let’s say I have a html form that I want in the dialog.  The href will need to point to that html…. ie. mycontroller/myaction/1

so if you had a list of links you have one jqm assigned:

$('.dialogs').jqm({ajax:'@href',modal:true, trigger: 'a.triggerLink'});

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

With the corresponding html links:

<a href=”mycontroller/myaction/1” class=”triggerLink”>Item 1</a>
<a href=”mycontroller/myaction/2” class=”triggerLink”>Item 2</a>
<a href=”mycontroller/myaction/3” class=”triggerLink”>Item 3</a>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

the controller action, based on the parameter passed with know, for instance, that you are selecting a particular item based on id to edit inside the dialog.

So, my last ‘issue/problem’ was – ‘what if I want to have this fire based on a select’ ?

Tricky but very doable:

take the above href – assign an id to it:

<a id=”editProviderLink” href=”#” class=”triggerLink”>Edit</a>

I also have a select with id ‘employeeProviderList’.  So, you select a provider name in a dropdown, and click the ‘edit’ href link

then, in the script (document.ready):

$("#editProviderLink").click(function(event) { 
        $(this).attr("href", "/MyController/MyAction/" + $('#employeeProviderList').val()); 
    });

 

this code will do the following:

when you click on the link, it will create the href attribute of the link, injecting in the url to call via ajax – this will occur before the jqmodal will fire (thankfully) – and open up the dialog with the corresponding html returned from the controller action.   This also can be done through the ‘onShow’

onShow (callback)

Called when a dialog is to be shown. Be sure to show (set visible) the dialog.

// onShow : show+make the window translucent
var myOpen=function(hash){ hash.w.css(‘opacity’,0.88).show(); };
$(‘#dialog’).jqm({onShow:myOpen});

Be sure to check out all the callback options!

There is a way as well to fire off a callback that will occur when the dialog is closed – which I sometimes do to update the underlying page via another ajax call  🙂

Hope this helps – its a bit complex, but once you dig into jqModal, it can very powerful – and especially with a MVC setup (like asp.net mvc).

An example that I will cover later is to create a html helper that encapsulates the logic to build a window.  ie.

<%= Html.jqmAjaxWindow<ClaimsController>("addDependentCareWindow","a.addDependentCareTrigger", 
    "Add Provider",true, c => c.LoadNewProviderView(ViewData.Model.Employee.Employeeid.ToString()), 
        new Hash(onHide=> "myClose"))%>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This dialog can be triggered with:

<a href="#" class="addDependentCareTrigger">Add</a>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

To get an idea of this helper code:

 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

public static string jqmAjaxWindow<TController>(this HtmlHelper helper, string dialogWindowName, string dialogTriggerName, 
           string dialogTitleText, bool isModel, Expression<Action<TController>> theAction, IDictionary options) 
           where TController : Controller 
        { 
            var sb = new StringBuilder(); 
            BuildChrome(sb, dialogWindowName, dialogTitleText); 
            sb.Append("<div class="jqmTarget clear"><p>...Loading Content...</p></div>"); 
            sb.Append("</div>"); 
            sb.Append("<script type='text/javascript'>"); 
            sb.Append("$(function() {"); 
            sb.AppendFormat("$('#{0}').jqm(", dialogWindowName); 
            sb.Append("{ajax: "); 
            sb.AppendFormat("'{0}', ", LinkBuilder.BuildUrlFromExpression<TController>(helper.ViewContext.RequestContext, 
                helper.RouteCollection, theAction)); 
            if (isModel) 
            { 
                sb.Append("modal: true, "); 
            } 
            foreach (DictionaryEntry option in options) 
            { 
                sb.AppendFormat("{0}:{1},", option.Key, option.Value); 
            } 
            sb.Append("target:'div.jqmTarget', "); 
            sb.AppendFormat("trigger:'{0}'", dialogTriggerName); 
            sb.Append("});"); //end of jqm 
            var browser = HttpContext.Current.Request.Browser; 
            if (browser.Browser != "AppleMAC-Safari") 
            { //problem with drag and chrome... 
                sb.AppendFormat("$('#{0}').draggable();", dialogWindowName); 
            } 
            sb.Append("});</script>"); //end of function() 
            return sb.ToString(); 
        }
 
private static void BuildChrome(StringBuilder sb, string dialogWindowName, string dialogTitleText)
        {
            string imagePath = VirtualPathUtility.ToAbsolute("~/Content/Images/Close.jpg");
            sb.AppendFormat("<div id="{0}" class="jqmWindow">", dialogWindowName); //outer window
            sb.Append("<div class="jqmTitleContainer jqDrag">");

            sb.AppendFormat("<div class="jqmTitle">{0}</div>", dialogTitleText); //title
            sb.Append("<div class="jqmCloseContainer">"); //start close container
            sb.AppendFormat("<a href="#" class="jqmClose"><img class="jqmCloseImage" src="{0}" 
               alt="Close"/></a>", imagePath);
            sb.Append("</div>"); //end close container
            sb.Append("</div>"); //end jqmTitleContainer
        }

jqModal Tips – ajax dynamic dialogs

I’ve been using jqModal to handle all my dialog ‘window’ forms on a current application.  I’m not going to get into all the details here, but rather expand on a few complex operations.

First, one powerful aspect of jqModal is the ability to assign a dialog based on a href trigger link.

Here is an example of what this means:

$(‘.dialogs’).jqm({ajax:’@href’,modal:true, trigger: ‘a.triggerLink’});

ajax

If passed, dialog contents will be loaded remotely via ajax. You can pass the URL (e.g. $.jqm({ajax:’remote/dialog.html’}) or extract it from an attribute of the triggering element. For instance, $(.jqm({ajax:’@href’}) would grab contents from bar.html if the triggering element was <a href=”foo/bar.html”>Open Dialog</a>. If a more complicated loading routine is desired, the onShow() callback should be leveraged.

So, let’s say you have the above as described where you want to open a dialog for a list of items : the above dialog contains the very important trigger reference that is saying ‘any a href with class ‘triggerLink’ will fire an event to open the dialog.

Then, the added functionality is ‘when this happens, it’s going to call to the href of that trigger to determine the ajax form to load.

Let’s say I have a html form that I want in the dialog.  The href will need to point to that html…. ie.  myform.html.   I could just do the following:

$('.dialogs').jqm({ajax:'myform.html',modal:true, trigger: 'a.triggerLink'});

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

When the trigger link is clicked ie. a href=”#” class=”triggerLink”  (brackets removed) it will open a dialog with the myform.html as it’s content.

This works particularly well with something like asp.net mvc.  ie. my system is to use a ascx (a snippet of html basically) that is loaded by calling a controller action.   Let’s say I have a html form that I want in the dialog.  The href will need to point to that html…. ie. mycontroller/myaction/1

so if you had a list of links you have one jqm assigned:

$('.dialogs').jqm({ajax:'@href',modal:true, trigger: 'a.triggerLink'});

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

With the corresponding html links:

<a href=”mycontroller/myaction/1” class=”triggerLink”>Item 1</a>
<a href=”mycontroller/myaction/2” class=”triggerLink”>Item 2</a>
<a href=”mycontroller/myaction/3” class=”triggerLink”>Item 3</a>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

the controller action, based on the parameter passed with know, for instance, that you are selecting a particular item based on id to edit inside the dialog.

So, my last ‘issue/problem’ was – ‘what if I want to have this fire based on a select’ ?

Tricky but very doable:

take the above href – assign an id to it:

<a id=”editProviderLink” href=”#” class=”triggerLink”>Edit</a>

I also have a select with id ‘employeeProviderList’.  So, you select a provider name in a dropdown, and click the ‘edit’ href link

then, in the script (document.ready):

$("#editProviderLink").click(function(event) {
        $(this).attr("href", "/MyController/MyAction/" + $('#employeeProviderList').val());
    });

 

this code will do the following:

when you click on the link, it will create the href attribute of the link, injecting in the url to call via ajax – this will occur before the jqmodal will fire (thankfully) – and open up the dialog with the corresponding html returned from the controller action.   This also can be done through the ‘onShow’

onShow (callback)

Called when a dialog is to be shown. Be sure to show (set visible) the dialog.

// onShow : show+make the window translucent
var myOpen=function(hash){ hash.w.css(‘opacity’,0.88).show(); };
$(‘#dialog’).jqm({onShow:myOpen});

Be sure to check out all the callback options!

There is a way as well to fire off a callback that will occur when the dialog is closed – which I sometimes do to update the underlying page via another ajax call  🙂

Hope this helps – its a bit complex, but once you dig into jqModal, it can very powerful – and especially with a MVC setup (like asp.net mvc).

An example that I will cover later is to create a html helper that encapsulates the logic to build a window.  ie.

<%= Html.jqmAjaxWindow<ClaimsController>("addDependentCareWindow","a.addDependentCareTrigger",
    "Add Provider",true, c => c.LoadNewProviderView(ViewData.Model.Employee.Employeeid.ToString()),
        new Hash(onHide=> "myClose"))%>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This dialog can be triggered with:

<a href="#" class="addDependentCareTrigger">Add</a>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

To get an idea of this helper code:

 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

public static string jqmAjaxWindow<TController>(this HtmlHelper helper, string dialogWindowName, string dialogTriggerName, 
           string dialogTitleText, bool isModel, Expression<Action<TController>> theAction, IDictionary options)
           where TController : Controller
        {
            var sb = new StringBuilder();
            BuildChrome(sb, dialogWindowName, dialogTitleText);
            sb.Append("<div class=\"jqmTarget clear\"><p>...Loading Content...</p></div>");
            sb.Append("</div>");
            sb.Append("<script type='text/javascript'>");
            sb.Append("$(function() {");
            sb.AppendFormat("$('#{0}').jqm(", dialogWindowName);
            sb.Append("{ajax: ");
            sb.AppendFormat("'{0}', ", LinkBuilder.BuildUrlFromExpression<TController>(helper.ViewContext.RequestContext, 
                helper.RouteCollection, theAction));
            if (isModel)
            {
                sb.Append("modal: true, ");
            }
            foreach (DictionaryEntry option in options)
            {
                sb.AppendFormat("{0}:{1},", option.Key, option.Value);
            }
            sb.Append("target:'div.jqmTarget', ");
            sb.AppendFormat("trigger:'{0}'", dialogTriggerName);
            sb.Append("});"); //end of jqm 
            var browser = HttpContext.Current.Request.Browser;
            if (browser.Browser != "AppleMAC-Safari")
            { //problem with drag and chrome... 
                sb.AppendFormat("$('#{0}').draggable();", dialogWindowName);
            }
            sb.Append("});</script>"); //end of function() 
            return sb.ToString();
        }
 
private static void BuildChrome(StringBuilder sb, string dialogWindowName, string dialogTitleText)
        {
            string imagePath = VirtualPathUtility.ToAbsolute("~/Content/Images/Close.jpg");
            sb.AppendFormat("<div id=\"{0}\" class=\"jqmWindow\">", dialogWindowName); //outer window
            sb.Append("<div class=\"jqmTitleContainer jqDrag\">");

            sb.AppendFormat("<div class=\"jqmTitle\">{0}</div>", dialogTitleText); //title
            sb.Append("<div class=\"jqmCloseContainer\">"); //start close container
            sb.AppendFormat("<a href=\"#\" class=\"jqmClose\"><img class=\"jqmCloseImage\" src=\"{0}\" 
               alt=\"Close\"/></a>", imagePath);
            sb.Append("</div>"); //end close container
            sb.Append("</div>"); //end jqmTitleContainer
        }

jQuery Tip with Select/Options

Although quite ‘simple’ – it seems I always forget the exact syntax here  🙂

So this is mostly a reminder post for myself!

To get the value of a select:

$('#select').val();

To get the text of the selected option:

$('#select :selected').text()
 
 

Unit Testing with RIA.NET

Vijay’s weblog has a good post on “Unit Testing Business Logic in .NET RIA Services“.  Good read.

From my understanding RIA.NET is going to be CTP in July, however, with one of the core items being that RIA.NET will utilize the underlying ADO.NET Data Services (Astoria) protocol.  I think this is a good move.

ADO.NET Data Services represents a REST approach to data services supporting IQueryable – (ie. Entity Framework, Linq to SQL, NHibernate Linq).

I look forward to seeing more out of RIA.NET.

(Related RIA.NET posts)

Domain-Driven Design By Eric Evans

I must say, emphatically, that Domain-Driven Design by Eric Evans should be a required read by any software engineer in the field that is using an object-oriented language (I can’t speak outside of that yet).

"This book belongs on the shelf of every thoughtful software developer."

–Kent Beck

This book has been out for awhile – I first read  Applying Domain-Driven Design and Patterns: With Examples in C# and .NET by Jimmy Nilsson – and although it was a good starter book, in retrospect, it would have been better for me to start from the source.

To me there is a ladder of growth emerging:

1. First the goal of writing code that follows good object oriented design.  ie. loosely coupled, encapsulation, programming w/interfaces, etc…

2. Then we see patterns emerge in that code base – ‘factory pattern, strategy pattern, inversion of control’ – not even as much as ‘in code’ but as a way to ‘talk about code’.  When one dev says to another ‘we need to use a factory here’ – it’s a common language.

3. Once these start to emerge, there is an architectural awareness – a ‘how do I fit these pieces together’.  DDD by Eric Evans (and Patterns of Enterprise Application Architecture by Martin Fowler) is the next great place to explore.

What is interesting is several projects I’ve seen were driven from a technology perspective and not from a domain driven one – and have required someone coming in and ‘saving’ the project.

In my current project it’s been an evolving model, expanding and refactoring as I have learned more of the business and it’s rules.  Our jobs as developers are twofold – be experts in the technologies we work in , but more than that – to learn how businesses work – to relate to customers, etc… it’s quite a task!  Many times I see organizations attempt to conquer the problem through the technology only without really grasping the domain being modeled.  

I started with the layered approach, and honestly began to learn how to shape the parts as the knowledge of the domain began to shape and form.  Evolving is the keyword, to me though – it’s a learning process, there are times that difficult decisions are made when shaping the code, and yet when trying to stick close to first being conscious and aware of ‘how’ I’m writing the code.  Having a DDD up front, separating the domain, repositories, understanding ‘specification’, ‘factories’, etc… all produce an environment where the software can shape and grow without becoming too unwieldy.   Eric Evans helps to shape and form his experience is a way that provides insight and wisdom into domain-driven development.

(see also http://domaindrivendesign.org/ )

Frustration: Castle.Windsor 2.0 and MvcContrib.Castle

First off, it’s really a shame that when an assembly is expecting a certain other assembly that the error messages would indicate which assembly is failing.

Case in point – MvcContrib.Castle was built with Castle.Windsor 1.x  – but the only error I get when building my project with the new Castle.Windsor 2.0 was that an assembly was expecting Castle.Windsor 1.x

I was pulling my hair out trying to figure it out – since I updated NHibernate to 2.1 with the new proxy setup (I’m using Castle’s DynamicProxy) I was fishing around attempting to figure it out.

Luckily I ran a nunit test that uses all those pieces minus the MvcContrib.Castle.  It worked.  So I was still stumped.

Finally it hit me that the MvcContrib had a register controllers functionality I was using that is sorta an adapter for Castle.Windsor.

So I went to get the latest, assuming that MvcContrib.Castle would be using the latest version of Castle.Windsor 2.0 which finally came out as a non-beta… nope.

I ended up getting the contrib source code, and rebuilding the MvcContrib.Castle pieces I needed with Castle.Windsor 2.0.

That is frustrating – most of it because of Visual Studio not giving me the pertinent information needed on why it failed.

Ah well.  At least I figured it out and got it to all work in the end  🙂