thoughts on coding

August 12, 2010

MVCContrib extension – Localized Labels, Description

Filed under: ASP.NET MVC, MVCContrib, Uncategorized — Frantisek @ 2:17 pm

I use MVCContrib library on one of my ASP.NET MVC 2 projects. That project should have multi-language support. I use InputBuilders quite much but InputBuilders don’t support the multilanguage features for i.e. Labels, Descriptions, etc..

So I realized to extend it.

So to fully understand this blog entry you nee to be familiar with MvcContrib InputBuilders and the way how the default multi-language support is done in ASP.NET MVC.

There is quite nice article written about the localization here. There are several ways how to store the multi-language texts but I like Adam’s guide because it’s quite easy.

My MVCContrib-multi-language extension

In my project I have the source code of MVCContrib, so it was easy to extend. I demonstrate my extension on Labels.

I created 2 classes:

    1 namespace MvcContrib.UI.InputBuilder.Attributes

    2 {

    3     public class LabelAttribute : Attribute

    4     {

    5         public Type LabelResourceType { get; set; }

    6         public string LabelResourceName { get; set; }

    7 

    8         private string _label;

    9 

   10         public string Label

   11         {

   12             get

   13             {

   14                 if (!string.IsNullOrEmpty(_label))

   15                 {

   16                     return _label;

   17                 }

   18 

   19                 if (LabelResourceType != null && !string.IsNullOrEmpty(LabelResourceName))

   20                 {

   21                     PropertyInfo property = LabelResourceType.GetProperty(LabelResourceName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

   22                     if (property != null)

   23                     {

   24                         var txt = property.GetValue(null, null) as string;

   25                         return txt;

   26                     }

   27                     return "Default:" + LabelResourceName;

   28                 }

   29 

   30                 return "";

   31             }

   32             set

   33             {

   34                 _label = value;

   35             }

   36         }

   37 

   38         public LabelAttribute()

   39         {

   40         }

   41 

   42         public LabelAttribute(string text)

   43         {

   44             Label = text;

   45         }

   46 

   47         public LabelAttribute(Type textResourceType, string textResourceName)

   48         {

   49             LabelResourceType = textResourceType;

   50             LabelResourceName = textResourceName;

   51         }

   52 

   53     }

   54 

   55     [AttributeUsage(AttributeTargets.Class)]

   56     public class LabelConventionAttribute : Attribute

   57     {

   58         public Type ResourceType { get; set; }

   59         public string Pattern { get; set; }

   60 

   61         public LabelConventionAttribute(Type resourceType, string pattern)

   62         {

   63             ResourceType = resourceType;

   64             Pattern = pattern;

   65         }

   66 

   67         public string GetLabelFor(string propertyName)

   68         {

   69             return new LabelAttribute(ResourceType, string.Format(Pattern, propertyName)).Label;

   70         }

   71     }

   72 }

Class LabelAttribute is to add the multilanguage support for the particular property. But because I’m lazy to write it on all properties of my model which is sent to the view, I create LabelConventionAttribute.

I like Convetion-over-Configuration style so using this attribute it is possible to setup the convention that the labels will be named by the convention Pattern.FormatWith(propetyName).

Next change was to change DefaultProperyConvention class to be partial. It’s due to the have my extensions in a separate class. I had to add there a method Lable

So here it’s

    1 namespace MvcContrib.UI.InputBuilder.Conventions

    2 {

    3     public partial class DefaultProperyConvention

    4     {

    5        

   17 

   18         public virtual string LabelForPropertyConvention(PropertyInfo propertyInfo)

   19         {

   20             if (propertyInfo.AttributeExists<LabelAttribute>())

   21             {

   22                 return propertyInfo.GetAttribute<LabelAttribute>().Label;

   23             }

   24             if (propertyInfo.ReflectedType.AttributeExists<LabelConventionAttribute>())

   25             {

   26                 return propertyInfo.ReflectedType.GetAttribute<LabelConventionAttribute>().GetLabelFor(propertyInfo.Name);

   27             }

   28             return propertyInfo.Name.ToSeparatedWords();

   29         }

   30     }

   31 }

   32 

And in the original DefaultPropertyConvention class I had to remove the method LabelForPropertyConvention.

That’s all. The similar steps can be done also for Description, but it’s necessary to extend PropertyViewModel class with new property.

The usage is:

    1 [DescriptionConvention(typeof(Descriptions), "Car_{0}")]

    2 [LabelConvention(typeof(Labels), "Car_{0}")]

    3 public class CarInput

    4 {

    5     [Required]

    6     [Example("BMW")]

    7     public virtual string Name { get; set; }

    8 }

Based on Adam’s guidance, I also had to create a resource file for the labels and the VS.NET created me the class Labels.

If you use MVCContrib builders then i.e. their Field.Master contains code like this: Html.Encode(Model.Label) to display the model’s label. Using the previously described extension it will be translated into the culture set in Thread.CurrentThread.CurrentUICulture.

That’s all for now …

Advertisements

August 11, 2010

Book Review: ASP.NET MVC 2 IN ACTION

Filed under: ASP.NET MVC, Di Factory, IoC, MVCContrib, NHibernate, StructureMap, Uncategorized — Frantisek @ 1:36 pm

I read MEAP version of the book ASP.NET MVC 2 in Action from Jeffrey Pallermo last month and I’d like to share my point of the view.

The book shows you how to use ASP.NET MVC 2 in Alt.Net (StuctureMap, MvcContrib, Rhino.Mocks, jQuery, NHibernate, NUnit, etc.) way – which I appreciate very much.

The book shows more how CodeCampServer.org was built connected with ASP.NET MVC 2, what is the logic, tips and tricks behind the designed solution. I must say, I like it as Headspring designed it. I just would call this book ASP.NET MVC 2 in Action on CodeCampServer project.

If you want to download and understand the code quite deeply, read this book. The quys around CodeCamperver are really cool ;o)!

If you want to know more about ASP.NET MVC 2 in general than how to use ASP.NET in Alt.NET, way then read this book: Pro ASP.NET MVC 2 Framework, Second Edition (Expert’s Voice in .NET)

IEnumarable with a Count = IEnumerableList

Filed under: .NET, Uncategorized — Frantisek @ 1:07 pm

I do Domain-Drive-Design (DDD) and one of the golder rules practically says that the domain model shouldn’t expose more necessary.

Example:

    1 public class Item

    2 {

    3     public IList<Bid> Bids

    4     {

    5         get; private set; }

    6 

    7     public Item()

    8     {

    9         Bids = new List<Bid>();

   10     }

   11 }

   12 

   13 public class Bid

   14 {

   15 }

The class Item has collection of the Bid(s). So Item can expose property IList Bids {get;}. The problem is that in case Bid has a reference to Item then it’s possible that that Bid1 whose parent item is Item1 is added to Item2. The designer of the domain model enable us to do it. This is violation of the domain model rules.

Solution: we should add method AddBid(Bid bid) {} to the class Item and change the Item’s property Bids to the following IEnumerable Bids {get;}

Fine, but what to do in case there is a logic which would like to know how many bids some item has. IEnumerable doesn’t expose such property. For such cases I create my IEnumerableList.

    1 public interface IEnumerableList<T> : IEnumerable<T>

    2 {

    3     /// <summary>

    4     /// Gets the <see cref="T"/> at the specified index.

    5     /// </summary>

    6     /// <value></value>

    7     T this[int index] { get; }

    8 

    9     /// <summary>

   10     /// Gets the count.

   11     /// </summary>

   12     /// <value>The count.</value>

   13     int Count { get; }

   14 }

and I also created the List implementation called EnumerableList:

    1 public class EnumerableList<T> : IEnumerableList<T>

    2 {

    3     private readonly IList<T> underlyingList;

    4 

    5     /// <summary>

    6     /// Initializes a new instance of the <see cref="EnumerableList&lt;T&gt;"/> class.

    7     /// </summary>

    8     /// <param name="list">The list.</param>

    9     public EnumerableList(IList<T> list)

   10     {

   11         underlyingList = list;

   12     }

   13 

   14     #region Implementation of IEnumerable

   15 

   16     /// <summary>

   17     /// Returns an enumerator that iterates through the collection.

   18     /// </summary>

   19     /// <returns>

   20     /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.

   21     /// </returns>

   22     /// <filterpriority>1</filterpriority>

   23     public IEnumerator<T> GetEnumerator()

   24     {

   25         return underlyingList.GetEnumerator();

   26     }

   27 

   28     /// <summary>

   29     /// Returns an enumerator that iterates through a collection.

   30     /// </summary>

   31     /// <returns>

   32     /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.

   33     /// </returns>

   34     /// <filterpriority>2</filterpriority>

   35     IEnumerator IEnumerable.GetEnumerator()

   36     {

   37         return underlyingList.GetEnumerator();

   38     }

   39 

   40     #endregion

   41 

   42     #region Implementation of IEnumerableList<T>

   43 

   44     /// <summary>

   45     /// Gets the <see cref="T"/> at the specified index.

   46     /// </summary>

   47     /// <value></value>

   48     public T this[int index]

   49     {

   50         get { return underlyingList[index]; }

   51     }

   52 

   53     /// <summary>

   54     /// Gets the count.

   55     /// </summary>

   56     /// <value>The count.</value>

   57     public int Count

   58     {

   59         get { return underlyingList.Count; }

   60     }

   61 

   62     #endregion

   63 }

And the final solution looks like the following:

    1 public class Item

    2    {

    3        public IEnumerableList<Bid> Bids

    4        {

    5            get

    6            {

    7                return new EnumerableList<Bid>(_bids);

    8            }

    9        }

   10        private IList<Bid> _bids;

   11 

   12        public Item()

   13        {

   14            _bids = new List<Bid>();

   15        }

   16 

   17        public void AddBid(Bid bid)

   18        {

   19            _bids.Add(bid);

   20        }

   21    }

   22 

   23    public class Bid

   24    {

   25    }

In this case the domain model doesn’t allow me to do prohibited action.

Original article was published at www.Catarsa.com

String FormatWith Extension

Filed under: Uncategorized — Frantisek @ 12:45 pm

There are plenty of cases when it’s necessary to display any data with the texts. Yes, you can use

string.Format(“My age is {0} year(s)”, age);

but I prefer more fluent interface so I wrote the following extension:

    1 public static string FormatWith(this string text, params object[] args)

    2 {

    3     if (text.IsNullOrEmpty())

    4     {

    5         return string.Empty;

    6     }

    7 

    8     return string.Format(text, args);

    9 }

and its usage is

“My age is {0} year(s)”.FormatWith(age)

Isn’t it more fluent and better to read?

The original article was published at http://catarsa.com/Blog/Kaduk-Frantisek/2010/8/Extensions_FormatWith

Create a free website or blog at WordPress.com.