MVP

It’s the second year that I am MVP for C# for Romania – and I feel good about it!

image

 

Thursday, April 01, 2010
Re: Andrei Ignat, Most Valuable Professional, Visual C#
To whom it may concern,

It is with great pride we announce that Andrei Ignat has been awarded as a Microsoft® Most Valuable Professional
(MVP) for 4/1/2010 – 4/1/2011. The Microsoft MVP Award is an annual award that recognizes exceptional
technology community leaders worldwide who actively share their high quality, real world expertise with users and
Microsoft. All of us at Microsoft recognize and appreciate Andrei’s extraordinary contributions and want to take this
opportunity to share our appreciation with you.
With fewer than 5,000 awardees worldwide, Microsoft MVPs represent a highly select group of experts. MVPs
share a deep commitment  to community and a willingness  to help others. They represent  the diversity of  today’s
technical communities. MVPs are present in over 90 countries, spanning more than 30 languages, and over 90
Microsoft  technologies. MVPs share a passion  for  technology, a willingness  to help others, and a commitment  to
community. These are the qualities that make MVPs exceptional community leaders. MVPs’ efforts enhance
people’s lives and contribute to our industry’s success in many ways. By sharing their knowledge and experiences,
and providing objective feedback, they help people solve problems and discover new capabilities every day. MVPs
are technology’s best and brightest, and we are honored to welcome Andrei as one of them.
To recognize the contributions they make, MVPs from around the world have the opportunity to meet Microsoft
executives, network with peers, and position themselves as technical community leaders. This is accomplished
through speaking engagements, one on one customer event participation and technical content development.
MVPs also receive early access to technology through a variety of programs offered by Microsoft, which keeps
them on the cutting edge of the software and hardware industry.
As a recipient of this year’s Microsoft MVP award, Andrei joins an exceptional group of individuals from around the
world who have demonstrated a willingness to reach out, share their technical expertise with others and help
individuals maximize their use of technology.
Sincerely,
Rich Kaplan
Corporate Vice President
Customer and Partner Advocacy
Microsoft Corporation

ASP.NET MVC , ORM and ViewModels

Since I am active on asp.net/mvc I find many peoples asking about

  1. One to many relationship .
  2. Dropdownlist
  3. How to use MVC with other ORM frameworks instead of Linq To Sql(L2S) ?
  4. What is a ViewModel and what is his purpose ?

For answering, I have made a small application with MVC2 in order to detail my answer.

First the problem :

You have Employees and Department.Each Employee belongs to an Department (let’s forget the fact that the employee can belong for a final date to the Department or any other life ideas)

The request is to create and view Employees .(forget delete,update – if I will have time and/or by general request , I will do this also this)

The database:

image

The beginning of the application :

First Layer , Data Access Layer
I use EF 3.5 (not 4.0 with POCO style – because is not ready yet) and make an edmx file and let EF put his classes.
You can use also ADO.NET with StoredProc, L2S, NHibernate or any other ORM you want.
Second Layer,Business Logic :
This is the layer where the logic should intervene (e.g., the name should be not null ).

Here is the list for Employee :

namespace BusinessLogic

{

    /// <summary>

    /// TODO : add IDataErroInfo in order to validate

    /// TODO : add the department

    /// </summary>

    public class Employee

    {

        public long ID;

        public string Name { get; set; }

        public Department Department{ get; set; }

        public void SaveNew()

        {

            //TODO : validate before save

            //TODO : automapper

            using (DAL_EF.testsEntities te = new DAL_EF.testsEntities("name=myconnection"))

            {

                DAL_EF.Employee e = new DAL_EF.Employee();

                e.Name = this.Name;

                //TODO : what if dept. deleted ?

                e.Department =te.Department.Where(d=>d.ID== this.Department.ID).FirstOrDefault();

                te.AddToEmployee(e);

                te.SaveChanges();

            }

        }

    }

    public class EmployeeList : List<Employee >

    {

        public void Load()

        {

            using (DAL_EF.testsEntities te = new DAL_EF.testsEntities("name=myconnection"))

            {

                foreach (var emp in te.Employee.Include("Department"))

                {

                    //TODO : use automapper

                    Employee e=new Employee() { ID = emp.ID, Name = emp.Name };

                    e.Department=new Department(){ ID=emp.Department.ID,Name=emp.Department.Name};

                    this.Add(e);

                }

            }

        }

    }

}

Please pay attention for Load procedure in EmployeeList : it uses the first layer, DAL, but it can use any ORM framework.

Third layer, ViewModel:

Because all the views for employees will need a select list for department ( either for sorting, creating or updating) I have put a base ViewModel class that retrieves the list of Departments:

namespace MVCAppEmp.Classes
{
    public class ViewModelEmployee
    {
        public static SelectList ListOfDepartments
        {
            get
            {
                //TODO : put this into cache to not load every time
                DepartmentList dl = new DepartmentList();
                dl.Load();
                return dl.SelectFromList(x => x.ID.ToString(), y => y.Name);
            }
        }
    }
    public class ViewModelEmployeeCreate : ViewModelEmployee
    {
        public Employee emp=new Employee();
    }
    public class ViewModelEmployeeList : ViewModelEmployee
    {
        public EmployeeList employees;
        public void Load()
        {
            employees = new EmployeeList();
            employees.Load();
        }
    }
}


Fourth Layer , MVC itself – view and controller :

<% =Html.ValidationSummary() %>
<% using (Html.BeginForm())
   { %>
    <h2>Create</h2>
    List of departments :
    <% =Html.DropDownList("DepartmentID", MVCAppEmp.Classes.ViewModelEmployee.ListOfDepartments)%>
    <%=Html.EditorFor(model => model.emp)%>
<input type="submit" value="create" />
<%} %>

and the controller

// POST: /Employee/Create
       // TODO: make a binding for employees
       [HttpPost]
       public ActionResult Create(Employee emp,long DepartmentID)
       {
           try
           {

               emp.Department = new Department() { ID = DepartmentID };
               emp.SaveNew();
               return RedirectToAction("Index");
           }
           catch(Exception ex)
           {
               ModelState.AddModelError("", ex.Message);
               return View(new ViewModelEmployeeCreate(){emp=emp});
           }
       }

So to answer the questions :

  1. One to many relationship – easy to do, most difficult to program
  2. Dropdownlist – easy – just transform a list into a select list, provided you have all data belongs
  3. How to use MVC with other ORM frameworks instead of Linq To Sql(L2S) ? Does not matter ! Just create your BusinessLogic and use that ORM!
  4. What is a ViewModel and what is his purpose ? To fill the data for GUI that BusinessLogic does not comply and transfer data to BusinessLogic. Reciprocally too!

You will find attached the application and the sql to create the database :

For MVC2  /MVC 3
http://msprogrammer.serviciipeweb.ro/wp-content/uploads/ASP.NETMVCORMandViewModels_135E/emp.zip

For MVC 4

http://msprogrammer.serviciipeweb.ro/wp-content/uploads/ASP.NETMVCORMandViewModels_135E/empMVC4.zip

What to do next, in order to familiarize yourself :
1. Make the update of the employees .Create view, save.
2. Filter the list of the employees on department. Search for all employees beginning with A that belong to IT department.
3. Search for TODO’s : there are part of other tutorials – but it will help you in MVC (and other!) development

This post have a continuation here:

http://msprogrammer.serviciipeweb.ro/2010/07/05/asp-net-mvc-and-dos-re-using-the-viewmodels/

ASP.NET MVC Extensions Methods

These are my extensions.

  1. Not display dropdownlist if the Select list is null
    public static MvcHtmlString DropDownListNull(this HtmlHelper html, string Name, SelectList select, object htmlAttributes)
    {
    
    if (select == null)
    return MvcHtmlString.Empty;
    else
     return html.DropDownList(Name, select, htmlAttributes);
    
    }
    
    
  2. Transform Enum to SelectList
    #region enum to list
            private static List<KeyValuePair<long, string>> FromEnum(this Type e)
            {
                List<KeyValuePair<long, string>> kvp = new List<KeyValuePair<long, string>>();
                foreach (var s in Enum.GetValues(e))
                {
                    kvp.Add(new KeyValuePair<long, string>((int)s, s.ToString()));
                }
                return kvp;
            }
            public static SelectList ToSelectList(this Type enumObj)
            {
    
                return new SelectList(enumObj.FromEnum(), "Key", "Value");
    
            }
            #endregion
    
  3. Transform Generic list into a SelectList
                  #region Generic List to SelectItem
            public static SelectList SelectFromList<TItem>(this List<TItem> values,
                Expression<Func<TItem, string>> key, Expression<Func<TItem, string>> value)
            {
                var Key = key.Compile();
                var Value = value.Compile();
                List<KeyValuePair<string, string>> kvp = new List<KeyValuePair<string, string>>(values.Count);
                values.ForEach(item =>
                    kvp.Add(new KeyValuePair<string, string>(Key.Invoke(item), Value.Invoke(item))));
    
                return new SelectList(kvp, "Key", "Value");
    
            }
            #endregion
    
    
  4. Display pager control
    #region paged list control
            //after http://geekswithblogs.net/nuri/archive/2009/08/05/mvc-paged-list.aspx
            /// <summary>
            /// Shows a pager control - Creates a list of links that jump to each page
            /// </summary>
            /// <param name="page">The ViewPage instance this method executes on.</param>
            /// <param name="pagedList">A PagedList instance containing the data for the paged control</param>
            /// <param name="controllerName">Name of the controller.</param>
            /// <param name="actionName">Name of the action on the controller.</param>
            public static void ShowPagerControl(this ViewPage page, BasePagedListImplementation pagedList, string formatUrl)
            {
                HtmlTextWriter writer = new HtmlTextWriter(page.Response.Output);
                if (writer != null)
                {
                    for (int pageNum = 1; pageNum <= pagedList.PageCount; pageNum++)
                    {
                        bool samepage=(pageNum == pagedList.PageNumber);
                        if (!samepage)
                        {
                            writer.AddAttribute(HtmlTextWriterAttribute.Href,string.Format(formatUrl, pageNum));
                            writer.AddAttribute(HtmlTextWriterAttribute.Alt, "Page " + pageNum);
                            writer.RenderBeginTag(HtmlTextWriterTag.A);
                        }
    
                        writer.AddAttribute(HtmlTextWriterAttribute.Class,
                                            pageNum == pagedList.PageNumber ?
                                                                "pageLinkCurrent" :
                                                                "pageLink");
    
                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.Write(pageNum);
                        writer.RenderEndTag();
    
                        if (!samepage)
                        {
                            writer.RenderEndTag();
                        }
                        writer.Write("&nbsp;");
                    }
    
                    writer.Write("(");
                    writer.Write(pagedList.TotalItemCount);
                    writer.Write(" items in all)");
                }
            }
    
            #endregion
    
    

Other extensions available that are good :

  1. http://blog.wekeroad.com/blog/asp-net-mvc-list-helper-extension-method/
  2. http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
  3. http://helios.ca/2009/09/21/asp-net-mvc-extension-methods-of-urlhelper/
  4. http://blog.donnfelker.com/2010/02/25/asp-net-mvc-tempdata-extension-methods/
  5. http://inq.me/post/ASPNet-MVC-Extension-method-to-create-a-Security-Aware-HtmlActionLink.aspx

If you know more, please tell me

My programmer tools in 2009

you can download the PDF from http://msprogrammer.serviciipeweb.ro/wp-content/uploads/2010/03/tools.pdf

Tool

Description

Link

SharpZipLib Zip files programatically http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx
nunit test http://www.nunit.org/index.php
svn source control http://subversion.apache.org/
hudson continous integration http://hudson-ci.org/
EntityFramework sql server database to .NET code
filehelpers parse csv and other files http://www.filehelpers.com/
log4net logging http://logging.apache.org/log4net/
lumisoft parsing email messages http://www.codeproject.com/KB/vista/SMTP_POP3_IMAP_server.aspx
moq mocking in unit test http://code.google.com/p/moq/
automapper transferring data between dal and bll http://www.codeplex.com/AutoMapper
pagedlist use for paging in ASP.NET MVC http://pagedlist.codeplex.com/
log4postsharp logging every method with easy http://code.google.com/p/postsharp-user-plugins/wiki/Log4PostSharp
postsharp see log4postsharp, version 1.5 still free http://www.sharpcrafters.com/
webdeployment project to deploy web projects http://www.microsoft.com/downloads/details.aspx?FamilyID=0AA30AE8-C73B-4BDD-BB1B-FE697256C459&amp;displaylang=en&displaylang=en
IIS SEO Toolkit verify my sites http://www.iis.net/expand/SEOToolkit
nbehave testing with words http://nbehave.org/
reflector analyze code, others and mine http://www.red-gate.com/products/reflector/
fiddler analyze ajax requests http://www.fiddler2.com/fiddler2
build utilities from apache svn commit if different http://msbuildtasks.tigris.org/
selenium testing web interfaces http://seleniumhq.org/
HtmAgilityPack saving web pages http://htmlagilitypack.codeplex.com/

Utilities

Description

Link

notepad++ no notepad http://notepad-plus.sourceforge.net/uk/site.htm
paint graphic editor
paint.net graphic editor http://www.paint.net/
7zip free archiver-un-archiver http://www.7-zip.org/
sysinternals bunch of windows utilities http://technet.microsoft.com/en-us/sysinternals/default.aspx
windows live writer blog http://download.live.com/writer
psr.exe new method to create help
logparser parse fast files http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07&displaylang=en
foxitreader pdf reader www.foxitsoftware.com/pdf/reader
yahoo instant messaging www.yahoo.com
skype instant messaging http://www.skype.com/intl/en/
dosbox old games redivivus http://www.dosbox.com/
vlc movie player http://www.videolan.org/vlc/
dvddecrypter and dvdshrink backup my movies http://www.mrbass.org/dvdrip/
magicdisk load iso files http://www.magiciso.com/tutorials/miso-magicdisc-overview.htm
freecommander norton commander http://www.freecommander.com/
winmerge compare files / folders http://winmerge.org/downloads/

Firefox addons

https://addons.mozilla.org/en-US/firefox/collection/ignatandrei

firebug
yahoo slow
webdeveloper
weave
morningcofee
measureit
htmlvalidator
faviconizetab
exchangebcebnr
colorzilla
addoncollector
googlenotebook
downloadstatusbar
goolepagespeed

As I was saying, you can download the PDF from http://msprogrammer.serviciipeweb.ro/wp-content/uploads/2010/03/tools.pdf

Saving Setting for Windows Forms

Saving and retrieving application settings

Every application that I have made needs at minimum two things, that we will put on the generic term “ settings “:

1. “remember” their state – information that are read at the beginning, write at the end of the program . We will name those “local settings” because there are different by each user that uses the application.

2. Connect with other applications (databases, web services, other programs ) and remember the “connection” settings – information that is read and does not change often ( number of writes is minimized). We will name this “global settings”.Most of the time the writing is realized by setup and/or a new application dedicated to application administration.

Usually the settings are saved in a file persisted on local hard disk. From the programmer perspective, there are four questions that arise:

1. when to save

2. where to save

3. how to save

4. how to make the information confidential.

When to save

The saving can be done in two separate moments: on installing the application and in running the application. Usually, the global settings(information that does not change often such as database connection) is persisted on application setup and read when the application starts. The local settings information (such as last action of the user) is read when the application starts and it is write at the application end.

Where to save

For a desktop application there are two places to save the data for a application : the folder where the applications is installed by the user (usually %programfiles% , can be obtained in .NET with Path.GetDirectoryName( Assembly.GetEntryAssembly().GetName().CodeBase)) and the local folder for application data for this user (%USERPROFILE%\AppData\Local – obtained in .NET with
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
). The first one is for global settings, the other one for local user settings.

How to save

We will enumerate here several methods, remaining for you the task to choose between the best. We will deliberately skip the method in which you use a file and you wrote information there in a proprietary format.
In the next examples we will save/retrieve two named properties : DatabaseConnection and LastAction
Save method 1 : from Settings within Visual Studio
You can create settings for your project very easy. Load your project in Visual Studio, click on toolbar Project=>Properties, select the tab “Settings” and create the settings. In the picture you will see two settings, one with user scope and one with application scope:
clip_image002
By default Visual Studio creates a class named “Settings” and puts code for retrieving/storing the settings that you create. More – the application settings does not have a “set” by default – it is normal since it is stored in application config file – an ordinary user cannot write this setting.
The code for retrieving/saving the settings is the following:
Console.WriteLine(Properties.Settings.Default.DatabaseConnection);
Console.WriteLine(Properties.Settings.Default.LastAction);
Properties.Settings.Default.LastAction = “difference”;
Properties.Settings.Default.Save();
//you can reset the values by
//Properties.Settings.Default.Reset();
For more details please refer to the following links :

· Application Settings Architecture , http://msdn.microsoft.com/en-us/library/8eyb2ct1.aspx

· Application Settings Overview , http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

Video tutorial : http://www.youtube.com/watch?v=-JDoZU0HBBo&feature=PlayList&p=70009BDDADB00AEF&index=1

Save method 2 : from application configuration file

You can read/save directly from application configuration file. Add an application configuration file to the project and a reference to System.Configuration . In the app.config file add
<appSettings>
<add key=”DatabaseConnection” value=”name=Stargate”/>
<add key=”LastAction” value=”add”/>
</appSettings>
And the code is the following:
var app=ConfigurationManager.AppSettings;
foreach (var key in app.AllKeys)
{
Console.WriteLine(string.Format(“{0}={1}”,key,app[key]));
}
Observation 1 : Please ensure you put in the app.config file file just global settings. Otherwise the application must have administrative rights to modify the app.config file.
Observation 2 : For asp.net applications , the modifying of Web.config will result in restarting the application – that is NOT a good behaviour.

Video Tutorial : http://www.youtube.com/watch?v=Axkt_KE0JX4&feature=PlayList&p=70009BDDADB00AEF&index=2


Save method 3 , create a new configuration :

This method is a combinations between method 2 and 3 : we have an intermediate class to save and we save in the config file . It is somewhat more to write about, but it is more safe – and can be modified and/or tested easily.
First we create the class :
public class MyConfig : ConfigurationSection
{
[ConfigurationProperty(“DatabaseConnection”)]
public string DatabaseConnection
{
get
{
return base[“DatabaseConnection”].ToString();
}
set
{
base[“DatabaseConnection”] = value;
}
}
[ConfigurationProperty(“LastAction”)]
public string LastAction
{
get
{
return base[“LastAction”].ToString();
}
set
{
base[“LastAction”] = value;
}
}
}
Next , we put in the application configuration file the settings :
<configSections>
<sectionGroup name=”MyApplicationSettings”>
<section name=”MyConfig” type=”AppSettingsConsole.MyConfig, AppSettingsConsole” restartOnExternalChanges=”false” allowDefinition=”Everywhere” />
</sectionGroup>
</configSections>
<MyApplicationSettings>
<MyConfig DatabaseConnection=”name=Stargate” LastAction=”add”>
</MyConfig>
</MyApplicationSettings>
And third we wrote code to retrieve :
MyConfig m = (MyConfig)System.Configuration.ConfigurationManager.GetSection(“MyApplicationSettings/MyConfig”);
Console.WriteLine(m.DatabaseConnection);
Console.WriteLine(m.LastAction);

Video Tutorial : http://www.youtube.com/watch?v=oglDeV7sc94&feature=PlayList&p=70009BDDADB00AEF&index=3

Save method 4, XML file :
This is the method with the more liberty. We can define any class we want to preserve properties – we just need to serialize the class.
public class MySettings
{
static XmlSerializer xs;
static MySettings()
{
xs = new XmlSerializer(typeof(MySettings));
}
public string DatabaseConnection { get; set; }
public string LastAction { get; set; }
public void SaveToFile(string NameFile)
{
using (StreamWriter sw = new StreamWriter(NameFile))
{
xs.Serialize(sw, this);
}
}
public static MySettings RetrieveFromFile(string NameFile)
{
using (StreamReader sw = new StreamReader(NameFile))
{
return xs.Deserialize(sw) as MySettings;
}
}
}
And the code to save is easier :
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string FileName = Path.Combine(folderPath, “mysettings.txt”);
MySettings ms = new MySettings();
ms.DatabaseConnection = “name=Stargate”;
ms.LastAction = “add”;
ms.SaveToFile(FileName);
MySettings msRetrieve = MySettings.RetrieveFromFile(FileName);
Console.WriteLine(ms.LastAction + ” — ” + ms.DatabaseConnection);
Video Tutorial : http://www.youtube.com/watch?v=MtK3zZYjfS0&feature=PlayList&p=70009BDDADB00AEF&index=0
Save method 5, Ini Files

http://jachman.wordpress.com/2006/09/11/how-to-access-ini-files-in-c-net/
http://www.codeproject.com/KB/cross-platform/INIFile.aspx
Save method 6, Database
It’s obvious that you can have a table with 3 columns :Object, Name and Value. Access this column with EF, L2S , NHibernate or any other framework
Save method 7, Registry

Just the code
using (RegistryKey r = Registry.CurrentUser.CreateSubKey(@”Software\App”))
{
{
r.SetValue(“myvalue”, “1”, RegistryValueKind.String);
}
}
using (RegistryKey r = Registry.CurrentUser.CreateSubKey(@”Software\App”))
{
Console.WriteLine(r.GetValue(“myvalue”));
}
Video Tutorial : http://www.youtube.com/watch?v=UeBPTbWgthM&feature=PlayList&p=70009BDDADB00AEF&index=4

Summary

In this chapter we have shown different ways to store application settings in various file formats. A final recommendation is to store application global data in config file (either web.config, either app.config) and local user in XML file ( in
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
folder). More, for each desktop application please provide a way to edit the config file – and make sure you request elevated privileges.