Code Sprouts

Wholesome Bits Of Tech

ASP.Net MVC ActionButton + AjaxHelper jQuery Extension(s)

clock April 28, 2009 08:24 by author ColinW

Download the Code

I’ve been working on quite a few different projects using ASP.Net MVC 1.0, and I frequently encounter two things that aren’t directly supported with the first release:

  • The lack of an ActionButton
  • The inability to send a view back asynchronously that includes javascript + html

The first issue is somewhat trivially solved by including an AjaxHelper Form wrapped around an input, but that is more code than I care to write for dozens of buttons scattered about my project(s)*.

For the second issue, the workaround I used to use is to include all the javascript that I need included in the base page.  It works, but it makes for a rather cluttered mess, and you needlessly include javascript that some users may never use ( or possibly include javascript for features a user shouldn’t have access to ).

A New AjaxHelper With jQuery

By replacing the existing AjaxHelper with a new one that utilizes jQuery, I’ve been able to implement both an ActionButton AND a way to return Views that include both javascript + html.

I’ve included a sample project containing the new helper extensions & the necessary javascript file used by the new form methods.  If you run the sample project, I’ve included a small example of the ActionButton & asynchronous javascript/html return:

image 

In order to use the project files in a different project, you’ll need to do a few things.

1) Include the files located in the sample project under AjaxHelperHarness.UI.Ajax somewhere in a dll referenced by your application:

image

2)  Include the jquery.ajaxform.js file into your web application:

image

3) Replace the current System.Web.Mvc.Ajax namespace with the one that houses the new AjaxHelper files ( in this case AjaxHelperHarness.UI.Ajax):

<namespaces>
    <add namespace="System.Web.Mvc"/>
    <add namespace="System.Web.Mvc.Html"/>
    <add namespace="AjaxHelperHarness.UI.Ajax"/>
    <add namespace="System.Web.Routing"/>
    <add namespace="System.Linq"/>
    <add namespace="System.Collections.Generic"/>
</namespaces>

4) Reference the jquery.ajaxform.js script file in either your master page or the content page:

<script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery.ajaxform.js") %>">
</script>

And you’re ready to roll!

The signatures are the same as the old AjaxHelper, so you won’t need to alter any code in order to utilize the enhanced extension methods.

Future Enhancements

While the current version of the AjaxHelper works well, I’m still debating a better way to handle form functions currently added thorugh the external javascript file.  I’d love to be able to have them automatically injected into the page, but I haven’t come up with a clean way to do so.  I’d love to use something similar to RegisterScriptInclude like we see in WebForms.

- Colin

 

* – On a more philosophical thought, I’ve been puzzled why there’s an ActionLink in the AjaxHelper and not an ActionButton.  In an ajax-enabled world, I view a link as something that will actually cause a page referesh, and a button as something that will cause an action to occur on a current page ( sans refresh ).  I’m guessing that the inclusion of the ActionLink in the AjaxHelper is just to keep it consistent with the HtmlHelper, but perhaps there’s a better one than that.



ASP.Net MVC DataList Extension

clock April 21, 2009 07:40 by author ColinW

The first release of Asp.Net MVC lacks an implementation of the DataList, so I’ve created a simple extension to the framework that provides basic DataList support.

I’ve based the DataList off of the excellent Grid extension found in the MvcContrib project.

Get the project files Here

Getting Started

In order to use the DataList extension you’ll need to reference an assembly that contains the DataList code, and add the correct namespace to the web.config.

In my sample solution, I’ve created a single project that contains the DataList code inside of an Asp.Net MVC Web project:

image

I reference the namespace in my Views/web.config:

<namespaces>
  <add namespace="DataListExtension.UI"/>
</namespaces>

Using the DataList

Once you’ve included the DataList into your project and setup the namespace, you’ll have a new extension method available in the HtmlHelper instance in your views.

The DataList uses the same pattern the MvcContrib Grid for constructing the actual DataList.  The HtmlHelper extension method returns an instance of the DataList<>, as do all the member functions in the DataList<> class.  This allows you to ‘chain’ calls to the DataList and configure it through the front-end code:

<% Html.DataList(Model.TestValues).Columns(3).Item(item =>
    {
        item.Template( dataItem => {
        %>
            <div style="border: solid 1px green;">
                This is number: 
                <span style="font-weight: bold;"><%= dataItem %></span>
            </div>  
        <%        
        });
    }).Render(); %>

What this code is doing is creating a DataList around the TestValues property of the model, settings the number of columns to 3, and then specifying the template to use for each item rendered:

image 

The call to render is required when using the <% %> syntax, and it will write directly to the current response buffer. Optionally, you can use the <%= %> syntax,  which will return a string ( which will eventually be rendered to the current response buffer ).

Along with using templates, you can also optionally use a partial view by calling item.PartialView(…).

Future Enhancements

The current version works for its initial intent of displaying vertically expanding list of items, however there’s an almost limitless amount of possible enhancements that can be added.  Some of the features I’ll be adding in the future include:

  • Paging
  • Adding the ability to pass attributes to the parent container
  • Adding Horizontal Repeating
  • Custom Renders to better control the HTML output

- Colin



Socket-Based Silverlight / WPF Chat Server

clock April 13, 2009 10:44 by author ColinW

One of the features introduced with Silverlight 2 is socket-based network communications.   While there are a few differences between Silverlight Sockets and WPF ( or Win Form ) Sockets, the code is surprisingly portable between the frameworks.

In an effort to show-case both the power of Silverlight 2 Sockets and their similarity to the standard .Net 3.5 Sockets ( used by WPF, Win Forms, Consoles, etc. ), I’ve created an example chat system that can host a front-end written in Silverlight or WPF.  The backend can be run by any .Net 3.5 application framework, and I’ve included both a WPF version as well as a Console version.

Download the Solution Here

Chat System Components

The core of the system is found in the ‘Chat’ project.  The core classes are:

  • Client – Handles a client connection and logic ( consumable by Silverlight and WPF )
  • Server – Manages all client connections and logic
  • UserSocket – Wraps all socket communication asynchronously, and is used by both the client & server
  • Message – All activity between client(s) and the server is done through messages.  Message contains methods to construct byte packets, or ( given a byte stream ) create a Message.

Silverlight-Specific Components

Silverlight connections cannot be made to a server unless the server you’re connecting to provides a valid policy file.  The way Silverlight handles this is by making a request to port 943 with the text “<policy-file-request/>”.  You must respond to the request with a valid AccessPolicy XML file that explicitly declares what URI’s may access the port you’re trying to connect to, and on what port you will accept connections.

I have wrapped all the functionality needed to serve an access policy into the class ‘PolicyServer’.  This class will listen on port 943, and respond to policy requests with either the default embedded policy file, or with any byte[] array you pass in ( it will need to be an access policy file that allows the port you’re trying to connect to, otherwise Silverlight will not connect ).

One of the restrictions to the Socket system in Silverlight 2 is that connections must be made on ports between 4502-4532. In order for the client to connect, the server must be running within that range, and the access policy file must specify the port(s) allowed.  The embedded example access policy file allow connections to any of the ports in that range.

Silverlight-Specific Code

All core components in the system are shared between Silverlight & WPF ( All files in the ChatSL project are linked to their counterparts in the Chat project ).  While almost all of the code is identical, there are two different sections of code that need to be different between clients.  I’m able to keep all the code in the same file by using # directives to check which library is being compiled.

The first directive conditional is in the creation of the EndPoint in the Client class:

#if SILVERLIGHT
endPoint = new DnsEndPoint(_host, _port);
#else
IPHostEntry hostEntry = Dns.GetHostEntry(_host);

IPAddress address = (from a in hostEntry.AddressList
where a.AddressFamily == AddressFamily.InterNetwork
select a).First();
endPoint = new IPEndPoint(address, _port);
#endif
 
For the Silverlight piece of this code, the Silverlight-only DnsEndPoint class is used to build the correct endpoint.  The non-Silverlight code does have the DnsEndPoint class, and we need to do a bit of work to retrieve a valid address for the host.  You might be tempted to just use code similar to the following:
 
endPoint = new IPEndPoint(IPAddress.Any, _port);

However on my machine, this pulls back the IPV6 protocol for the endpoint, which won’t work with our socket ( which we specify as IPV4 ).  To handle the issue, I query the address list for the correct protocol and select the first match.
 
Included Projects

The included solution contains 7 projects:

  • Chat – Contains the core classes of the chat system
  • ChatSL – Silverlight library that LINKS to the files in the Chat project.
  • ConsoleServer – Runs the Chat server in a console
  • SilverlightUI – Runs the client as a Silverlight Application
  • SilverlightUI.Web – Host the Silverlight Client Application
  • WPFServer – Runs the Chat server as a WPF application
  • WPFUI – Runs the client as a WPF Application

I’m contemplating adding this solution to Code Project, and to periodically make updates to the Server & Client to support new functionality.  If you have any questions with the code, or if you’d like to see new features added, leave a comment or feel free to email me at colinw@codesprouts.com

- Colin



Creating A DatePicker Extension In ASP.Net MVC

clock April 7, 2009 06:35 by author ColinW

Selecting a date comes up frequently in web applications, so in this post I’m going to be walking us through building an extension method that will generate a jQuery datepicker input that will seamlessly bind with model data on an action post-back. So let’s get started!

* Download the complete project here:

Downloading DatePicker Component & Setting Up References

The jQuery DatePicker script is not part of the core download.  It’s a separate download from the jQuery UI, so you’ll need to download that first.  The download page is structured as a package download for the various components, but you can successfully get everything you need by un-checking all but the datepicker component and clicking the download button:

image

Download the file and extract it into a (clean) directory. 

While the download does contain a custom javascript file to include the components you downloaded, we’re going to skip that script file and extract out only the datepicker components we need.

From the directory you extracted the download file, navigate to ‘development-bundle\themes\base’, and copy the contents of that directory into the ‘Content’ directory of your solution ( do this through visual studio and it’ll automatically include the files into the project):

image

Now navigate over to ‘development-bundle\ui’ in the directory you extracted the files to and copy ‘ui.core.js’ & ‘ui.datepicker.js’ into the ‘Scripts’ folder in your solution:

image

No Calendar is complete without an icon, so go ahead and grab this one:

http://www.codesprouts.com/Images/calendar.gif

And copy it into your ‘Content/images’ folder in the project:

image

That’s it for resources, but we need to setup references in order to use jQuery & access the css files.  I’m using a brand-new project and will be working in the ‘Views/Home/Index.aspx’ view, so I can add script & css references ot the ‘Views/Shared/Site.Master’ file and they will be available in the Index.aspx page.  I added the following references into the <head> element of the master:

<link href="../../Content/ui.all.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="../../Scripts/jquery-1.3.2.js"></script>
<script type="text/javascript" src="../../Scripts/ui.core.js"></script>
<script type="text/javascript" src="../../Scripts/ui.datepicker.js"></script>

And with that, we should be able to start playing with our DatePicker extension!

Working With The DatePicker

Before we can wrap everything up into an extension method, we need to get the base functionality working first.  If you’re using a brand new project, navigate to your Index page, and include the following code in the view:

Date: <input type="text" id="date" />
    
<script type="text/javascript">
     $(function() {
          ("#date").datepicker();
     });
</script>

Run the project, and you should now see a functioning date picker when you click in the textbox:

image 

Excellent!

In our date input above, we’re using the defaults for all options of the datepicker, so let’s change that a bit before we wrap this up into a helper extension.

I’d rather have the datepicker show immediately, and have an image button for the popup, so we’ll need to change the call to .datepicker() to the following:

$("#date").datepicker({
                showOn: 'button',
                buttonImage: '/Content/images/calendar.gif',
                duration: 0 
                });

You can find the description for all options at http://docs.jquery.com/UI/Datepicker .

If you run the site to view the lastest changes, you’ll now see a pretty calendar icon that can be clicked to popup the calendar:

image

Perfect!

Creating A Helper Extension

Now that we’ve created a working date picker, let’s put it into an extension method in order to clean up the UI & allow us to use it elsewhere.

Create a new folder in the root of the project, called ‘UI’, and create a new class called ‘HtmlHelperExtensions.cs’ in our new folder:

image

In the new class, add the following method to the class ( You’ll need to add a using clause to System.Web.MVC & System.Text ):

public static string DatePicker(this HtmlHelper helper, string name, string imageUrl, object date)
{
    StringBuilder html = new StringBuilder();
 
    // Build our base input element
    html.Append("<input type=\"text\" id=\"" + name + "\" name=\"" + name + "\"");
 
    // Model Binding Support
    if (date != null)
    {
        string dateValue = String.Empty;
 
        if (date is DateTime? && ((DateTime)date) != DateTime.MinValue)
            dateValue = ((DateTime)date).ToShortDateString();
        else if (date is DateTime && (DateTime)date != DateTime.MinValue)
            dateValue = ((DateTime)date).ToShortDateString();
        else if (date is string)
            dateValue = (string)date;
 
        html.Append(" value=\"" + dateValue + "\"");
    }
 
    // We're hard-coding the width here, a better option would be to pass in html attributes and reflect through them
    // here ( default to 75px width if no style attributes )
    html.Append(" style=\"width: 75px;\" />");
 
    // Now we call the datepicker function, passing in our options.  Again, a future enhancement would be to
    // pass in date options as a list of attributes ( min dates, day/month/year formats, etc. )
    html.Append("<script type=\"text/javascript\">$(document).ready(function() { $('#" + name + "').datepicker({ showOn: 'button', buttonImage: '" + imageUrl + "', duration: 0 }); });</script>");
 
    return html.ToString();
}

Since we’ve added it as an extension method, if we add the namespace into the view web.config, we’ll be able to call our new method from the HtmlHelper of the view. 

To add the namespace, open up your web.config ( you can either use the web.config in the ‘View’ folder, or go to the root and add it there ), and add the following into the namespaces element:

<add namespace="YourProjectNameGoesHere.UI"/>

In my example project, the name of the project is ‘DatePickerHarness’, so my complete namespaces element looks like the following:

<namespaces>
    <add namespace="System.Web.Mvc"/>
    <add namespace="System.Web.Mvc.Ajax"/>
    <add namespace="System.Web.Mvc.Html"/>
    <add namespace="System.Web.Routing"/>
    <add namespace="System.Linq"/>
    <add namespace="System.Collections.Generic"/>
    <add namespace="DatePickerHarness.UI"/>
</namespaces>

Now that we’ve got that in there, we can access the extension method from within our view:

image

Now that we have the abillity to call our extension method, let’s make this a bit more exciting and wrap everything into a form that will post back to an action in our controller.  First we’ll need to add our complete form to the frontend:

<% using (Html.BeginForm("AddAWeek", "Home"))
   { %>
<table>
    <tr>
        <td>
            Date:
        </td>
        <td>
            <%= Html.DatePicker("Date", "/Content/images/calendar.gif", 
                                this.ViewData["TheDate"]) %>
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="submit" value="Add A Week" />
        </td>
    </tr>
</table>
<% } %>

And a bit of code to our controller:

public ActionResult AddAWeek(DateTime? Date)
{
    if (Date == null)
        Date = DateTime.Now;
 
    Date = Date.Value.AddDays(7);
 
    this.ViewData["TheDate"] = Date;
    
    return View("Index");
}

And then we can run it:

image

Changing the date to May 18th, and hitting ‘Add A Week’ displays the following after the post-back:

image

Fantastic!

The Wrap-Up

With just a little bit of work, we’ve now created a reusable component for displaying & capturing dates with the ASP.Net MVC Framework. Any view we create within the project now has the new DatePicker extension method available, significantly cutting down on the time it would take to code it from scratch each time.

The include project contains everything we’ve done here, and also includes a few overloads to make the DatePicker extension a bit more robust.  If you’re not happy with the way the datepicker works or how it looks, feel free to change the rendered script in the extension method(s) as you see fit.

Till next time!

- Colin



Welcome to BlogEngine.NET 1.5.0

clock April 1, 2009 20:00 by author Administrator

If you see this post it means that BlogEngine.NET 1.5.0 is running and the hard part of creating your own blog is done. There is only a few things left to do.

Write Permissions

To be able to log in to the blog and writing posts, you need to enable write permissions on the App_Data folder. If you’re blog is hosted at a hosting provider, you can either log into your account’s admin page or call the support. You need write permissions on the App_Data folder because all posts, comments, and blog attachments are saved as XML files and placed in the App_Data folder. 

If you wish to use a database to to store your blog data, we still encourage you to enable this write access for an images you may wish to store for your blog posts.  If you are interested in using Microsoft SQL Server, MySQL, VistaDB, or other databases, please see the BlogEngine wiki to get started.

Security

When you've got write permissions to the App_Data folder, you need to change the username and password. Find the sign-in link located either at the bottom or top of the page depending on your current theme and click it. Now enter "admin" in both the username and password fields and click the button. You will now see an admin menu appear. It has a link to the "Users" admin page. From there you can change the username and password.  Passwords are hashed by default so if you lose your password, please see the BlogEngine wiki for information on recovery.

Configuration and Profile

Now that you have your blog secured, take a look through the settings and give your new blog a title.  BlogEngine.NET 1.4 is set up to take full advantage of of many semantic formats and technologies such as FOAF, SIOC and APML. It means that the content stored in your BlogEngine.NET installation will be fully portable and auto-discoverable.  Be sure to fill in your author profile to take better advantage of this.

Themes and Widgets

One last thing to consider is customizing the look of your blog.  We have a few themes available right out of the box including two fully setup to use our new widget framework.  The widget framework allows drop and drag placement on your side bar as well as editing and configuration right in the widget while you are logged in.  Be sure to check out our home page for more theme choices and downloadable widgets to add to your blog.

On the web

You can find BlogEngine.NET on the official website. Here you'll find tutorials, documentation, tips and tricks and much more. The ongoing development of BlogEngine.NET can be followed at CodePlex where the daily builds will be published for anyone to download.

Good luck and happy writing.

The BlogEngine.NET team