Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
DZone MVB

Links

Social

November 2009 - Posts

ASP.NET MVC: Creating reports using Chart control

ASP.NET Chart control is powerful control you can use to add charting support to your web applications. Although chart controls are mainly used with ASP.NET forms it is not very hard to use them also in ASP.NET MVC applications. In this posting I will show you how to use ASP.NET Chart control in ASP.NET MVC application and I will illustrate how to do it easily so you don’t mess up your views.

Before we start coding I want to make some notes about my solution:

  • this solution is pretty new and it is sure that one can improve the code provided here,
  • using this solution I’m trying to generalize in-place reporting for MVC applications,
  • also I’m trying to keep my views as clean as possible – chart definitions are not small if you have more complex charts or if you want very nice looking charts.

If you are not familiar with ASP.NET Chart control then please read my blog posting <asp:Chart>. You find there simple introduction to this free control and also all necessary links.

Solution overview

What we are trying to build here is shown on the following diagram. Our main goal is to avoid using ASP.NET forms elements in our MVC line user interface. Also we want to generalize reporting support so we have one interface for all reports.

Solution overview

I introduce here pretty simple report. If you have more complex reports then you can extend reporting interface shown below later. You may also find useful to reorganize outputing system. I am using here simple works-for-me or works-for-prototyping solution. I want to focus on point and let’s try not to lose it.

Reporting interface

Before we create our first report let’s define interface for it. This interface must define all basic actions we need to do with reports:

  • set source with report data,
  • bind data to report,
  • write report image to some (output) stream.

This is my reporting interface. Note that DataSource has only setter – it is because I don’t have currently need to ask data from chart. I only provide data to it.


public interface IReportControl : IDisposable

{

    void DataBind();

    object DataSource { set; }

    void SaveChartImage(Stream stream);

}


As you can see this interface is pretty thin. I am sure that it will grow in the future when need for more complex reports appears.

Sample report

Let’s define one report for testing purposes. Add web user control called MyReport.ascx to Reports folder of your web application and drag ASP.NET Chart control on it. Here is definition of my control.


<%@ Control Language="C#" AutoEventWireup="true"
    CodeBehind="LastEnquiriesChart.ascx.cs"
    Inherits="ReportingApp.Web.Reports.LastEnquiriesChart"
%>

<%@ Register
    assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

    namespace="System.Web.UI.DataVisualization.Charting"

    tagprefix="asp"
%>

 

<asp:Chart ID="Chart1" runat="server" Palette="Excel"

    Height="200px" Width="200px">

    <series>

        <asp:Series Name="Series2"

            CustomProperties="DrawingStyle=Emboss"

            XValueMember="Date"
           
YValueMembers="Count"
           
IsValueShownAsLabel="True"

            Font="Microsoft Sans Serif, 8pt"
            LabelBackColor="255, 255, 192"

            LabelBorderColor="192, 192, 0"
            LabelForeColor="Red">          

        </asp:Series>

    </series>

    <chartareas>

        <asp:ChartArea Name="ChartArea1" BorderDashStyle="Solid">

            <AxisX
                IntervalAutoMode="VariableCount"
                IntervalOffsetType
="Days"

                IntervalType="Days"
               
IsLabelAutoFit="False"
               
IsStartedFromZero="False">

                <MajorGrid 
                   
Interval="Auto"
                   
IntervalOffsetType="Days"
                    IntervalType
="Days" />

            </AxisX>

        </asp:ChartArea>

    </chartareas>

    <Titles>

        <asp:Title 
            Font="Microsoft Sans Serif, 8pt, style=Bold"

            Name="Title1"

            Text="Last week enquiries">

        </asp:Title>

    </Titles>

</asp:Chart>


If you look at the definition and consider it as simple one you understand why I don’t want this mark-up to be there in my views. This is just one simple report. But consider for a moment three complex reports. 90% of my view will be one huge report definition then and I will miss all the good things that views have.

As I want this report to be interfaced with my reporting mechanism I make it implement IReportControl interface. Code-behind of my control is as follows.


public partial class LastEnquiriesChart : UserControl, IReportControl

{

    public object DataSource

    {

        set

        {

            Chart1.DataSource = value;

        }

    }

 

    public override void DataBind()

    {

        base.DataBind();

        Chart1.DataBind();

    }

 

    public void SaveChartImage(Stream stream)

    {

        Chart1.SaveImage(stream);

    }

}


All other user controls we are using for reporting must also implement IReportControl interface. This leads us to one interesting finding – we don’t have to host only chart control in our user controls, we have to host there whatever ASP.NET forms control we need for reporting. We can also create wrapper controls that get report image from some other external source (let’s say we have some COM component that is able to return reports as images).

Creating loader

Now we have sample report control and interface we can use to provide data and catch output of report. It is time to create meeting place for two worlds: ASP.NET forms and ASP.NET MVC framework. I created class called ReportLoader. The name of this class is good enough for me because it tells me that this is the integration point between two worlds. Let’s look at loader implementation now.


public static class ChartLoader

{

    public static void SaveChartImage(string controlLocation,
    IEnumerable data, Stream stream)

    {

        using (var page = new Page())

        using (var control = (IReportControl)
               page.LoadControl("~/Reports/" + controlLocation))

        {

            control.DataSource = data;

            control.DataBind();

            control.SaveChartImage(stream);

        }

    }

}


Loader does one trick: it doesn’t render the control. It only runs as long as report is written to stream and then it disposes user control and temporary page instance to avoid all other actions they may take. I made ChartLoader and SaveChartImage methods as static because I don’t need hell load of classes and super-cool architecture right now.

Creating controller action

We are almost there… Let’s create now controller action that returns chart image. As I am prototyping my application I use very robust controller action. You may be more polite coders and I strongly suggest you to read Bia Securities blog posting BinaryResult for Asp.Net MVC. You can find BinaryResult implementation also from MVC Contrib project.


[HttpGet]

public ActionResult GetChart()

{           

    var repository = Resolver.Resolve<IPriceEnquiryRepository>();

    var enquiries = repository.ListPriceEnquiries();

    var data = from p in enquiries

               group p by p.Date.Date into g

               select new { Date = g.Key, Count = g.Count() };

 

    Response.Clear();

    Response.ContentType = "image/png";

    ChartLoader.SaveChartImage(

                "LastEnquiriesChart.ascx",

                data,

                Response.OutputStream);           

    Response.End();           

 

    return null; // have to return something

}


Now we have controller action that asks data from somewhere, prepares it for report and asks report as image from ChartLoader. Before outputing the report Response is cleared and content type is set to PNG. After writing image to response output stream the response is ended immediately to avoid any mark-up that may be written there otherwise.

As you can see I created special automatic objects for reporting. If you look at my report definition you can see that x-axis is bound to Date and y-axis to Count. You can also prepare reporting data in some near-DAL class methods and then slide this data through controller to report. The choice is yours.

Adding report to view

ASP.NET Chart control output Now let’s link report to view. We just have to add one simple img tag to our view and make it src to call out GetChart() method defined above.


<img
    src="<%= Url.Action("GetChart")%>
    alt="Last week enquiries
    title="Last week enquiries"
/>


Output of report is shown on right. I don’t have much data here and my report is not very nice but it works. Now, if you are not too tired or bored, it is time to make your chart very nice and show it to your boss or customer.

Conclusion

Mixing forms and MVC worlds of ASP.NET doesn’t always have to end up with hard mess. In this posting I showed you how to add simple but pretty generic reports support to your ASP.NET MVC application. Due to good interfacing we achieved separation between forms and MVC templates and linking reports to views is very-very simple.

Of course, code and interfaces represented here are not production-ready examples. But they give you right direction and you can always improve design of my solution. My point was to illustrate how to mix MVC and forms world in reporting context and I feel like I succeeded this time. What do you think? :)

Visual Studio 2010: Generating sequence diagrams on the fly

One nice feature that Visual Studio 2010 provides is generating sequence diagrams on the fly. Just point out method and choose diagram generating option from context menu. In this posting I will show you how to generate sequence diagrams on the fly.

To keep example illustrative and simple I will use simple code. Let’s suppose we have ASP.NET MVC application with following controller.


public class PriceEnquiryController : Controller

{

    // ... some properties and methods ...

 

    public ActionResult Index()

    {

        var model = new PriceEnquiryListModel();

        model.PriceEnquiries = PriceEnquiryRepository.ListPriceEnquiries();

 

        return View(model);

    }

}


Visual Studio 2010: Sequence diagram generation optionsLet’s say we want to generate sequence diagram for this method. All we have to do is to right click on method with mouse, select “Generate Sequence Diagram …” and modify some options.

You can select what kind of calls you want to include and exclude. Setting these options you can make diagram to reflect only those parts of your code that you really need to visualize.

If you look at the image you see that you can also set call depth. With more complex methods it may be very helpful because too large call depth causes huge diagram with too much knowledge on it.

When we are done with options we have to click “OK” button and Visual Studio 2010 generates sequence diagram. You can click on image to see it in original size.

Visual Studio 2010: Sequence diagram

This diagram is pretty simple and primitive but you can also generate more complex diagrams. Just set options you need and let Visual Studio 2010 generate – it works like charm. Let’s hope we get more diagrams when Visual Studio 2010 first stable version is released.


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
Shout it!
ASP.NET 4.0: Writing custom output cache providers

Until now we can use ASP.NET default output cache. We don’t have any option to write our own output cache mechanisms. ASP.NET 4.0 introduces extensible output cache – programmers can write their own output cache providers. In this posting I will show you how to write your own output cache provider and give you my sample solution to download.

Preparing

Before we begin with caching we need Visual Studio 2010 solution that has two projects – one web application and one class library. Class library is for output cache provider and web application is for testing purposes. My solution uses following names:

  • Solution: CacheProviderDemo
  • Web application: CacheProviderApp
  • Class library: MyCacheProviders

Before moving on let’s modify web application and add project reference to class library. In this case we don’t have to copy our cache provider to GAC after each build.

Configuring output caching

Now let’s change our web.config and add there the following configuration block under system.web section.


<caching>

<outputCache defaultProvider="AspNetInternalProvider">

  <providers>

   <add name="FileCache"

    type="MyCacheProviders.FileCacheProvider, MyCacheProviders"/>

  </providers>

</outputCache>

</caching>


This configuration block tells ASP.NET that there is output cache provider called FileCache available but we want to use default provider calles AspNetInternalProvider. We will change this block later.

Writing output cache provider

Now let’s start with output cache provider. From output cache configuration block you can see that Class1.cs in our class library must be renamed to FileCacheProvider.cs. Don’t forget also change the class name. Add reference to System.Web to class library and open FileCacheProvider.cs. In the beginning of this file add using line for System.Web.Caching namespace.

Our output cache provider class must extend OutputCacheProvider base class. This base class defines all methods that output cache providers must implement. Our output cache provider uses file system for cache storage. Output cache entries are serialized to binary format and back when writing and reading objects from files.

Classes for our custom output cache provider are here.


public class FileCacheProvider : OutputCacheProvider

{

    private string _cachePath;

 

    private string CachePath

    {

        get

        {

            if (!string.IsNullOrEmpty(_cachePath))

                return _cachePath;

 

            _cachePath = ConfigurationManager.AppSettings["OutputCachePath"];

            var context = HttpContext.Current;

 

            if (context != null)

            {

                _cachePath = context.Server.MapPath(_cachePath);

                if (!_cachePath.EndsWith("\\"))

                    _cachePath += "\\";

            }

 

            return _cachePath;

        }

    }

 

    public override object Add(string key, object entry, DateTime utcExpiry)

    {

        Debug.WriteLine("Cache.Add(" + key + ", " + entry + ", " + utcExpiry + ")");

 

        var path = GetPathFromKey(key);

 

        if (File.Exists(path))

            return entry;

 

        using (var file = File.OpenWrite(path))

        {

            var item = new CacheItem { Expires = utcExpiry, Item = entry };

            var formatter = new BinaryFormatter();

            formatter.Serialize(file, item);

        }

 

        return entry;

    }

 

    public override object Get(string key)

    {

        Debug.WriteLine("Cache.Get(" + key + ")");

 

        var path = GetPathFromKey(key);

 

        if (!File.Exists(path))

            return null;

 

        CacheItem item = null;

 

        using (var file = File.OpenRead(path))

        {

            var formatter = new BinaryFormatter();

            item = (CacheItem)formatter.Deserialize(file);

        }

 

        if (item == null || item.Expires <= DateTime.Now.ToUniversalTime())

        {

            Remove(key);

            return null;

        }

 

        return item.Item;

    }

 

    public override void Remove(string key)

    {

        Debug.WriteLine("Cache.Remove(" + key + ")");

 

        var path = GetPathFromKey(key);

 

        if (File.Exists(path))

            File.Delete(path);

    }

 

    public override void Set(string key, object entry, DateTime utcExpiry)

    {

        Debug.WriteLine("Cache.Set(" + key + ", " + entry + ", " + utcExpiry + ")");

 

        var item = new CacheItem { Expires = utcExpiry, Item = entry };

        var path = GetPathFromKey(key);

 

        using (var file = File.OpenWrite(path))

        {

            var formatter = new BinaryFormatter();

            formatter.Serialize(file, item);

        }

    }

 

    private string GetPathFromKey(string key)

    {

        return CachePath + MD5(key) + ".txt";

    }

 

    private string MD5(string s)

    {

        var provider = new MD5CryptoServiceProvider();

        var bytes = Encoding.UTF8.GetBytes(s);

        var builder = new StringBuilder();

 

        bytes = provider.ComputeHash(bytes);

 

        foreach (var b in bytes)

            builder.Append(b.ToString("x2").ToLower());

 

        return builder.ToString();

    }

}


With cached item we have to keep date and time that say us when cached object expires. I write simple CacheItem class that is marked as serializable (otherwise it is not possible to serialize it and therefore we cannot use binary formatter). CacheItem class is simple.


[Serializable]

internal class CacheItem

{

    public DateTime Expires;

    public object Item;

}


I made this class internal because we have no reason to show it to the world. We only use this class to store and restore cache entries with expiry date.

Some notes for FileCacheProvider class.

  • You must have appSetting called OutputCachePath that contains path to cache files folder. This path may contain ~ because in the case of web application this path goes through Server.MapPath() method.
  • File names are made of MD5 hashed cache entry key and .txt extension. You can use whatever file extension you like.
  • I am using binary formatter because it workes better for me than XmlSerializer (Add() method is used with internal classes that have no public constructor with empty argument list).
  • My code uses calls to Debug.WriteLine() method. When you run web application with Visual Studio then you can see output cache messages in output window. I found that it is very easy and powerful way to debug provider because these messages show you what is going on.

Preparing web application for testing

Let’s prepare now web application for testing. As a first thing we must make some changes to web.config. We have to add appSetting for cache folder and we have to make our file cache provider as default output cache provider. Here are XML-blocks for configuration.


<appSettings>

  <add key="OutputCachePath" value="~/Cache/" />

</appSettings>

 

<caching>

  <outputCache defaultProvider="FileCache">

    <providers>

      <add name="FileCache" type="MyCacheProvider.FileCacheProvider, MyCacheProvider"/>

    </providers>

  </outputCache>

</caching>


I expect you know where to put these blocks in web.config file. We have one more change to make before running our web application. Let’s turn output caching on for it. Although there should be providerName attribute available it doesn’t work yet. At least for my installation of Visual Studio 2010 and ASP.NET 4.0. Add the following line to Default.aspx.


<%@ OutputCache VaryByParam="ID" Duration="300" %>


I added VaryByParam for one reason: to test caching with different ID-s. Cache duration is 300 seconds (5 minutes). You can change to attributes if you like.

Testing output cache provider

Now let’s test our output cache provider. Run web application.

Web application: we are using it to test output cache provider

When you see default page in your browser check out output window in Visual Studio 2010. You should see there something like this.


Cache.Get(a2/default.aspx)
Cache.Add(a2/default.aspx, System.Web.Caching.CachedVary, 31.12.9999 23:59:59)
Cache.Set(a2/default.aspxHQNidV+n+FCDE, System.Web.Caching.OutputCacheEntry, 19.11.2009 12:20:56)

After refresh you should see something like this in output window.


Cache.Get(a2/default.aspx)
Cache.Get(a2/default.aspxHQNidV+n+FCDE)
Cache.Get(a2/styles/site.css)
Cache.Get(a2/webresource.axd)
Cache.Set(a2/styles/site.css, System.Web.Caching.OutputCacheEntry, 20.11.2009 12:17:09)
Cache.Add(a2/webresource.axd, System.Web.Caching.CachedVary, 31.12.9999 23:59:59)
Cache.Set(a2/webresource.axdHQNdVjnaEMMY-tPD2-oCbZFp7vHhVoQiB8SS98KHQMNKjUfs1FCDE, System.Web.Caching.OutputCacheEntry, 19.11.2010 12:17:09)
Cache.Get(a2/webresource.axd)
Cache.Get(a2/webresource.axdHQNdVqx_c6oOlTqymCAsGZh_8JA2FCDE)
Cache.Add(a2/webresource.axd, System.Web.Caching.CachedVary, 31.12.9999 23:59:59)
Cache.Set(a2/webresource.axdHQNdVqx_c6oOlTqymCAsGZh_8JA2FCDE, System.Web.Caching.OutputCacheEntry, 19.11.2010 12:17:10)

You see that second request caches some more data. There requests to FileCacheProvider are made by ASP.NET. During additional refresh some resources get cached and the other resources are removed from output cache.

Here is one simple screenshot fragment of file cache folder.

List of files that contain cache entries

You can open these files to see what is inside them. You should see there cache items in binary format as binary formatter serializes them.

Conclusion

Although there are not much informative and guiding documentation about custom output cache providers I got mine working seemlessly well. I am not sure about some aspects of my provider and I will consult with Microsoft about my doubts. Of course, I will let you know if I get some valuable feedback from Microsoft.

The point of this posting was to show you how to write custom output cache provider. As we saw it is not something crucial or complex – we have to extend OutputCacheProvider class and implement some methods that store, edit and clear cached items. You can write your own implementations of output cache provider and keep your output cache wherever you like.

Sample solution

Visual Studio 2010 Solution CacheProviderDemo.zip
Visual Studio 2010 Solution | Size: 181 KB

kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
Loading Enterprise Library validation rules from external file

Keeping validation rules in web.config may grow it pretty long and it is not convenient to make changes there anymore. Developers can manage validation rules easily by using Enterprise Library Configuration tool and therefore there is no good reason to handle validation rules manually. In this posting I will show you how to load validation rules from external configuration files.

Creating file for validation rules

Create new XML-file to your project and name it as Validation.config. I suggest .config extension because IIS blocks all requests to configuration files. Run Enterprise Library Condiguration tool and insert some validation rules.

Enterprise Library: Configuration tool

Save changes and close configuration tool.

Loading validation rules from external file

Now open the class where you handle validation logic. In my last posting ASP.NET MVC: Validating objects using Enterprise Library validation application block I gave you some idea about how to use validation in your application. There was class called Validator that took object and validated it. All validation errors are returned as array.


public static class Validator

{

    public static ValidationError[] Validate<T>(T instance)

    {

        var errors = new List<ValidationError>();

        var results = Validation.Validate<T>(instance);

 

        foreach (var result in results)

        {

            var error = new ValidationError();

            error.PropertyName = result.Key;

            error.Message = result.Message;

            errors.Add(error);

        }

 

        return errors.ToArray();

    }

}


In Validate<T>() method all validation rules are read from web.config. We have to modify this method to make it read validation rules from Validation.config. Here is the class with modifications.


public static class Validator

{

    public static ValidationError[] Validate<T>(T instance)

    {

        var errors = new List<ValidationError>();
 

        var source = new FileConfigurationSource("Validation.config");

        var validator = ValidationFactory.CreateValidatorFromConfiguration<T>(source);

        var results = validator.Validate(instance);

 

        foreach (var result in results)

        {

            var error = new ValidationError();

            error.PropertyName = result.Key;

            error.Message = result.Message;

            errors.Add(error);

        }

 

        return errors.ToArray();

    }

}


Validation rules are now read from Validation.config file and your web.config is lighter than before. Enterprise Library made this move very easy – only couple of lines of code were modified. Keeping validation rules in separate file is also safer – you don’t have to touch web.config to make modifications to validation rules.


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
Shout it!
ASP.NET MVC: Validating objects using Enterprise Library validation application block

Data validation is important topic in applications. There are many validation frameworks available and there should be one that you are happy with. I am currently playing with Enterprise Library 4.1 Validation Application Block and I am integrating it to my ASP.NET MVC application. In this posting I will show you how to use validation block in your ASP.NET MVC application.

Note. This posting gives you first ideas about validation and shows you how to get things done quick and dirty. For production-ready validation there more steps to follow and I will introduce these steps in my future postings. Stay tuned!

Introduction

Shortly, you can create ASP.NET MVC views that craete and initialize objects for you. I assume you know this feature and you know how it works at basic level.

Here is how my application is layered.

Currently all external stuff is referenced by infrastructure layer. Infrastructure layer provides common interfaces for dependency injection and validation. These interfaces doesn’t change when implementations change. Presentation layer uses infrastructure resolver to get implementations of repositories.

Adding validation

I have Enteprise Library 4.1 downloaded and installed on my development machine. If you want to just test my solution you can also create one ASP.NET MVC web application project and put all stuff there. No problem at all. After installing Enterprise Library you need some references so your application can use validation block. Take these files:

  • Microsoft.Practices.EnterpriseLibrary.Common.dll
  • Microsoft.Practices.EnterpriseLibrary.Validation.dll
  • Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.Design.dll

These libraries should be enough. I added references to these libraries to my infrastructure library.

As a next thing we need facade for our validation feature. I created these three classes:

  • ValidationError – represents one validation error and contains properties for invalid property name and validation message.
  • ValidationException – exception type that contains array of validation errors (it is also possible to detect validation caused errors in code).
  • Validator – this class has only one method called Validate<T> and it makes all the real work.

Let’s see those classes now.

ValidationError


public class ValidationError

{

    public string PropertyName { get; set; }

    public string Message { get; set; }

}


ValidationException


public class ValidationException : Exception

{

    private readonly ValidationError[] _errors;

 

    public ValidationException(ValidationError[] errors)

    {

        _errors = errors;

    }

 

    public ValidationError[] ValidationErrors

    {

        get

        {

            return _errors;

        }

    }

}


Validator


public static class Validator

{

    public static ValidationError[] Validate<T>(T instance)

    {

        var errors = new List<ValidationError>();

        var results = Validation.Validate<T>(instance);

 

        foreach (var result in results)

        {

            var error = new ValidationError();

            error.PropertyName = result.Key;

            error.Message = result.Message;

            errors.Add(error);

        }

 

        return errors.ToArray();

    }

}


Now we are almost done and it is time to add some rules.

Adding validation rules

Make sure you have web.config file in your application because we are going to modify it. Run Enterprise Library configuration program from all programs menu and open your web.config file.

Enterprise Library Configurator: Adding new validation block

Add some validation rules for you classes and save configuration. Enterprise Library Configurator creates all required sections to your web.config file automatically.

Validating objects

As a first thing take a look at this simple form that let’s users insert new price enquiries.


<h2>Insert</h2>

<%= Html.ValidationMessage("_FORM") %>

<% using (Html.BeginForm()) {%>

  <fieldset>

  <legend>New price enquiry</legend>

  <table>

    <tr>

      <td valign="top"><label for="Title">Title</label>:</td>

      <td valign="top">

        <%= Html.TextBox("Title") %><br />

        <%= Html.ValidationMessage("Title")%>

      </td>

    </tr>

    <tr>

      <td valign="top">

        <label for="From">From</label>:

      </td>

      <td valign="top">

        <%= Html.TextBox("From") %><br />

        <%= Html.ValidationMessage("From")%>

      </td>

    </tr>

    <tr>

      <td valign="top"><label for="DocNumber">Number</label>:</td>

      <td valign="top">

        <%= Html.TextBox("DocNumber") %><br />

        <%= Html.ValidationMessage("DocNumber") %>

      </td>

    </tr>

    <tr>

      <td valign="top"><label for="Date">Date:</label>:</td>

      <td valign="top">

        <%= Html.TextBox("Date", DateTime.Now.ToShortDateString()) %><br />

        <%= Html.ValidationMessage("Date") %>

      </td>

    </tr>

    <tr>

      <td valign="top">

        <label for="DueName">Due date:</label>:

      </td>

      <td valign="top">

        <%= Html.TextBox("DueDate", DateTime.Now.ToShortDateString()) %><br />

        <%= Html.ValidationMessage("DueDate") %>

      </td>

    </tr>

  </table>

 

  <p>

    <input type="submit" value="Save" />

  </p>

</fieldset>


Let’s see one repository method that accepts object to be validated. Let’s assume we have repository that validates objects before saving them. If there are validation errors ValidationException will be thrown. Here is simplified save method of repository.


public void SavePriceEnquiry(PriceEnquiry instance)

{

    var results = Validator.Validate<PriceEnquiry>(instance);

    if (results.Length > 0)

        throw new ValidationException(results);

    Save<PriceEnquiry>(instance);

}


And let’s use this repositoy in ASP.NET MVC controller (if your version of ASP.NET MVC doesn’t support HttpPost sttribute you can use AcceptVerbs(HttpVerbs.Post) instead).


[HttpPost]

public ActionResult Insert(PriceEnquiry enquiry)

{

    try

    {

        _repository.SavePriceEnquiry(enquiry);

    }

    catch (ValidationException vex)

    {

        Helper.BindErrorsToModel(vex.ValidationErrors, ModelState);

        return Insert();

    }

    catch (Exception ex)

    {

        ModelState.AddModelError("_FORM", ex.ToString());

        return Insert();

    }

    return RedirectToAction("Index");

}


You can see call to method called BindErrorsToModel(). This is helper method that steps through validation errors array and binds errors to current model. You can take this method and use it in your own projects if you like.


public static class Helper

{

    public static void BindErrorsToModel(ValidationException exception, ModelStateDictionary modelState)

    {

        BindErrorsToModel(exception.ValidationErrors, modelState);

    }
 

    public static void BindErrorsToModel(ValidationError[] errors, ModelStateDictionary modelState)

    {

        if (errors == null)

            return;

        if (errors.Length == 0)

            return;

 

        foreach (var error in errors)

            modelState.AddModelError(error.PropertyName, error.Message);

    }

}


NB! Don’t forget that fields in your views must be named like properties of class you are expecting as a result of binding.

Now you can test your application and see if validation works. You should see correct error messages if everything went well and there are no bugs in code or configuration.

Conclusion

Although this example is long one it is not hard to add validation support to your applications. It takes you some time if it is your first time but if you are familiar with tools and you keep yourself from planning rocket sience level validation then everything goes fast and smooth.

There are some more nyances you should know before stating that you fully suppor validation through your application. I will introduce some more ideas in my future postings about validation.


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
vote it on WebDevVote.com Shout it!
Visual Studio 2010: Visualizing dependencies

Visual Studio 2010 introduces new and cool feature – architecture diagrams that visualize dependencies between assemblies, namespaces and classes. In this posting I will show you how these diagrams look like and provide some explanations about how to read them.

I tested architecture diagrams (or should I say dependency diagrams?) with one of my small projects. Okay, I tried to visualize dependencies found in source code of KiGG too but it was too big for current implementation of dependency visualizer. But for smaller projects it works pretty well.

You can find these diagrams from Architecture menu of Visual Studio 2010.

Assembly dependencies

As a first thing I generated dependency diagram for assemblies. There is one main dll and it is related to violet block labeled as Generics. Blue block is my assemby and generics block shows all the generics I am using. Externals block is for external assemblies and on the following screenshot it is expanded so you can see other assemblies on what my own assembly one depends.

Visual Studio 2010: Assembly dependencies diagram
Visual Studio 2010: Assembly dependencies diagram.
Click on image to view it at original size.

Namespace dependencies

Namespace dependencies diagram illustrates dependecies between namespaces. Also here you can see Generics and Externals boxes. Purpose of them is same as before. On the following screenshot you can see class dependencies in my project. Bookmarks2LiveWriter box is expanded and it contains classes in this namespace. Class ExceptionBox is also expanded and you can see how method dependencies are visualized.

Visual Studio 2010: Namespace dependencies
 Visual Studio 2010: Namespace dependencies diagram.
Click on image to view it at original size.

Class dependencies

Class dependencies diagram illustrates dependencies between classes. As on previous diagrams you can see also on this diagram the lines with different thickness between classes. Thickness of line gives you some idea about how dependent one class is of another. Thicker line means heavier dependency. Direction on line shows what class is using what other class.

Visual Studio 2010: Class dependencies diagram
Visual Studio 2010: class dependencies diagram.
Click on image to view it at original size.

Custom dependencies

Visual Studio 2010: Generate dependency graph You can also generate custom dependency diagrams that illustrate things ust like you want. The result is something like you can see on screenshots above. Only new thing is dialog that lets you specify what you can see on diagram.

You can see this dialog on right and if it is too small for you then please click on it to see it at original size.

Right are in this dialog is reserved for example diagram. If you change the state of check boxes you can see on example how generated diagram looks like. After clicking Ok custom architecture diagram will be generated.

Matrix View

It is possible to view dependencies also as matrix. You can see dependencies matrix on following screenshot. You can see that I have disabled some options in legend – it is because otherwise matrix will be very large.

Visual Studio 2010: Matrix view 
Visual Studio 2010: Matrix view of dependencies.
Click on image to view it at original size.

Conclusion

Dependency diagrams are very useful tools when you analyze dependencies between different components in your system. Less dependencies mean usually less problems because changing one part of system causes less changes to other parts of system. I think these diagrams are good addition to code analysis reports because sometimes one picture can tell more than 1000 words.

Currently dependency diagrams are generated pretty slowly. But I hope it will me much faster when first stable version of Visual Studio 2010 hits the streets. Currently you can save diagrams as XPS files and it also possible to copy diagram or legend to clipboard as image. It is pretty easy to take those diagrams and make them part of your project documents.


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
Shout it!
Adding uberVU badge to your blog

uberVU is service that monitors how your blog entries (or other web resources) are performing in different social networks. You can integrate uberVU reaction count badge to your blog and monitor popularity of your blog entries right in your blog. In this posting I will show you how to add uberVU badge to your blog without any server-side coding.

You can find uberVU patch from uberVU tools page. There is also JavaScript given that you can use on your blog or home page. If you plan to insert this badge manually then you don’t need any additional work. But I am lazy guy and I want to put it up once so it works for all pages in my blog.

The example JavaScript is as follows (of course, uberVU may change it as they wish):


<script type="text/javascript">

  var ubervu_url = "http://your-url";

  var ubervu_title = "Your Page Title";

  var ubervu_style = "regular";

</script>

<script type="text/javascript" src="http://badge.ubervu.com/badge.1.0.js"></script>


But here are some problems:

  1. you must hardcode URL of the page,
  2. you must hardcode page title.

With couple of lines of code you can make it work on all of your pages. If uberVU badge code looks still like this then you can use the following code that works for every page.


<script>

  var url = document.location.href;

  if(url.indexOf('#') > -1)

  url = url.substr(0, url.indexOf('#'));

 

  var ubervu_url = url;

  var ubervu_title = document.title;

  var ubervu_style = "regular";

</script>

<script type="text/javascript" src="http://badge.ubervu.com/badge.1.0.js"></script>


Basically I just find current page URL and title with JavaScript and assign them to appropriate uberVU variables. Easy! :)

Visual Studio 2010: UML modeling projects

Visual Studio 2010 introduces modeling projects that bring UML diagrams to Visual Studio. Currently it is not possible to generate classes from diagrams automatically but I don’t think it is a problem – good UML diagrams visualize different aspects of system short and clearly and they usually don’t document everything you can find in system. In this posting I will show you how to use modeling projects in Visual Studio 2010.

Creating modeling projects

Modeling projects are created as all other projects. Select New Project from menu and select Modeling Projects from templates pane. There is only one modeling project template called (very originally) Modeling Project. Select it and click Ok.

Visual Studio 2010: Creating modeling project

Modeling project is practically empty when it is created. On the left side of screen you should see UML Model Explorer (you can open it from View => Other Windows menu). To add new objects to UML model just right click on the title with mouse and select object type.

UML Model Explorer

Visual Studio 2010: UML Model Explorer You can see UML Model Explorer on image at right. I took this screenshot after adding some objects to my modeling project so you can see how this window looks like when there is some content.

You can add new objects to you model simply by right clicking on model name and selecting object type you want to add. You can define object attributes and assign values to its properties right in the UML Model Explorer.

As a next thing let’s see some example diagrams I created. There are some features I miss (like saving diagrams as image files) but diagramming works pretty fine for program in beta status. Here are my example diagrams.

Adding new diagram

New diagrams are added to model just like any other file in other projects. Just select Add new item and select item type. You can click on image below to see it at original size.

Visual Studio 2010: Add new diagram to modeling project

You can see in the item types list all diagrams you can add to modeling project. I am not very sure if this list is final or not because some diagram types are missing. But let’s hope the best as always.

Adding items to diagrams

After adding new diagram or opening existing ones you can add objects to diagram. You can find objects specific to diagram from toolbox. Screenshots below show you toolboxes for activity, class and user case diagrams.

Visual Studio 2010: Activity diagram toolbox Visual Studio 2010: Class diagram toolbox Visual Studio 2010: Use case diagram toolbox

Class diagram

UML class diagram shows classes in system (or subsystem) and relations between classes. Modeling projects show also attributes and methods of classes. I created simple class diagram that visualizes Party generalization and shows how this generalization can easily connect addresses to Person and Company classes.

Visual Studio 2010: UML class diagram

If you have larger model that doesn’t fit to screen well you can hide members area of classes and save some more room for classes that are not visible otherwise.

Use case diagram

UML use case diagrams illustrate use cases in system (or subsystem) and actors who are related to use cases. Also relations between use cases are shown and commented if needed. My example shows simple registration process where user is identified by its digital passport and then approved by adminitrator when registration data is saved.

Visual Studio 2010: Use case diagram

Activity diagram

As final example here is my activity diagram. It is simple one and it only shows you how activity diagrams look like – don’t look for any deep thoughts from this example.

Visual Studio 2010: Activity diagram

There are also some good news about modeling projects. If you read Code stubbing with Visual Studio 2010 UML modeling thread from Visual Studio 2010 Beta 2 forums you can find out that modeling projects are built as easily extensible parts of projects and Microsoft is working also on code generation features. So, stay tuned – something big is happening!


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
Shout it!
Visual Studio 2010 Beta 2 downloads

Here are some download links to Visual Studio 2010 Beta 2 and related technologies.

Visual Studio

Team Foundation Server

Visual Studio SDK-s

Learn


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
Shout it!
Using ASP.NET and Jcrop to crop images online

Cropping images in ASP.NET is easy task to do if you use right tools. In this posting I will introduce how to crop images using Jcrop and System.Drawing namespace classes. What we are building is simple and user-friendly image cropping interface that also demonstrates some simple features of Jcrop. Believe me, your users will love it!

Jcrop is jQuery based library that brings crop margins selection to client side. Before starting you need two (free) JavaScript libraries:

After downloading them create new ASP.NET Web Application project and unpack those libraries to js directory. Also copy file js/Jcrop/css/Jcrop.gif to root folder of your project and add image you want to crop to same folder.

Expected result

As a first thing we will show image to user and some informative labels under image. And, of course, there is button for cropping.

ASP.NET + Jcrop: Selecting cropping area

You can see those values changing under image when you change the size or location of cropping are box.

When user clicks crop button then image will be cropped and shown to user. In our current case the result will be something like shown on following screenshot.

ASP.NET + Jcrop: Image after cropping

You can crop image again and again and again until you get the result you like.

Code

This is my ASP.NET form. I have to warn you that my JavaScript is written just to make it work and it needs some more cosmetics if you plan to use this code in real development. So, no hard feelings, okay?


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Crop.aspx.cs" Inherits="BlogExamples.Crop" %>

<!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></title>

    <link rel="Stylesheet" type="text/css" href="js/Jcrop/css/jquery.Jcrop.css" />

    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>

    <script type="text/javascript" src="js/Jcrop/js/jquery.Jcrop.min.js"></script>

    <script type="text/javascript">

        var editorID = '<%= _imageEditor.ClientID %>';

        jQuery(function() {

            jQuery('#' + editorID).Jcrop({

                onChange: showCoords,

                onSelect: showCoords

            });

        });

 

        function showCoords(c) {

            var tdX = document.getElementById('tdX');

            var tdY = document.getElementById('tdY');

            var tdWidth = document.getElementById('tdWidth');

            var tdHeight = document.getElementById('tdHeight');

 

            tdX.innerHTML = c.x;

            tdY.innerHTML = c.y;

            tdWidth.innerHTML = c.w;

            tdHeight.innerHTML = c.h;

 

            var xField = document.getElementById('<%= _xField.ClientID %>');

            var yField = document.getElementById('<%= _yField.ClientID %>');

            var widthField = document.getElementById('<%= _widthField.ClientID %>');

            var heightField = document.getElementById('<%= _heightField.ClientID %>');

 

            xField.value = c.x;

            yField.value = c.y;

            widthField.value = c.w;

            heightField.value = c.h;

        }

    </script>

</head>

<body>

    <form id="form1" runat="server">

    <div>

    <asp:Image runat="server" ID="_imageEditor" ImageUrl="MY_FILE.JPG" />

    </div>

    <table border="0" cellpadding="2" cellspacing="0">

    <tr>

    <td>x:</td>

    <td id="tdX">-</td>

    <td>y:</td>

    <td id="tdY">-</td>

    <td>width:</td>

    <td id="tdWidth">-</td>

    <td>height:</td>

    <td id="tdHeight">-</td>

    <td><asp:Button runat="server" ID="_cropCommand" onclick="_cropCommand_Click" Text="Crop" /></td>

    </tr>

    </table>

 

    <input type="hidden" runat="server" id="_xField" />

    <input type="hidden" runat="server" id="_yField" />

    <input type="hidden" runat="server" id="_widthField" />

    <input type="hidden" runat="server" id="_heightField" />

 

    </form>

</body>

</html>


And here is code-behind file of my form. If you plan to use this code in real development then you must validate values of crop margins before using them with drawing methods. Also you need error handling and you have to make sure that all objects will be disposed correctly.


using System;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Web.UI;

 

namespace BlogExamples

{

    public partial class Crop : Page

    {

        protected void _cropCommand_Click(object sender,
            EventArgs e)

        {

            var x = int.Parse(_xField.Value);

            var y = int.Parse(_yField.Value);

            var width = int.Parse(_widthField.Value);

            var height = int.Parse(_heightField.Value);

 

            using(var photo =
                  Image.FromFile(Server.MapPath("MY_IMAGE.JPG")))

            using (var result =
                  new Bitmap(width, height, photo.PixelFormat))

            {

                result.SetResolution(
                        photo.HorizontalResolution, 
                        photo.VerticalResolution);

 

                using (var g = Graphics.FromImage(result))

                {

                    g.InterpolationMode = 
                         InterpolationMode
.HighQualityBicubic;

                    g.DrawImage(photo,

                         new Rectangle(0, 0, width, height),

                         new Rectangle(x, y, width, height),

                         GraphicsUnit.Pixel);

                    photo.Dispose();

                    result.Save(Server.MapPath("MY_IMAGE.JPG"));

                }

            }

        }

    }

}


Well, that’s it. If you have any troubles running this code then please drop me a comment here and I will try to help you.


kick it on DotNetKicks.com pimp it 顶 Progg it Shout it
vote it on WebDevVote.com Shout it!
More Posts Next page »