Tag: ASP.NET MVC

Clearer MVC

In every application there are some variables that are set by the ASP.NET  application(  ASP.NET_SessionId  cookie ) and some that are set by the programmer( cached data in Application/Session/Cache/Cookies and so on).

I wanted every time to have a page where I can “clear” / delete those – and not found. So it’s the Clearer project.

It consists of :

  1. ClearerController with 2 Actions:   Index and DeleteItem
  2. 2 Views : Index.cshtml and EditAppData.cshtml
  3. Different Models:
    • SourceData  – enum  – can be  :  None ,        Application ,        Cache ,        Session ,        Cookies
    • AppData –  maintains Key/Value and SourceData pairs
    • ListAppData – loads data from Application , Cache , Session , Cookies  – and deletes.

To make an example, I have put in the Application_Start and Session_Start different values. So the screen is the following:

image

What I learn from the code:

  1. The Cookies, Applications, Session , Cache items can be easily converted to an DictionaryEntry and the code can be like this:
     DictionaryEntry de = new DictionaryEntry(item, sess[item.ToString()]);
     AddNew(de, SourceData.Session);
    
  2. Code must be error prone – what if some item in Session is null ? So , if I have the Key, all is good:
    private void AddNew(DictionaryEntry de, SourceData sd)
            {
                AppData ap = new AppData() { source = sd, Key = de.Key.ToString() };
                try
                {
                    var obj = de.Value;
                    ap.Value = (obj == null) ? Null : obj.ToString();
                }
                catch (Exception ex)
                {
    
                    ap.Value = string.Format(ErrorToString, ex.Message);
                }
                this.Add(ap);
            }
    
  3. The dog-food is good: I have followed my advice from msprogrammer.serviciipeweb… and it works ( used for Remove )
       [HttpPost]
            public JsonResult DeleteItem(string TheKey, int Source)
            {
                try
                {
                    var lad = new ListAppData();
                    lad.DeleteItem(TheKey, (SourceData)Source);
                    return Json(new { ok = true, message = "" });
                }
                catch (Exception ex)
                {
                    return Json(new { ok = false, message = ex.Message });
                }
                
            }
    
  4. When you pass strings in Javascript, there is a simple way to encode: HttpUtility.JavaScriptStringEncode
    <a href="javascript:removeItem('@HttpUtility.JavaScriptStringEncode(Model.Key)','@((int)Model.source)','@id')">Remove</a>
    

Possible uses:

  1. For developers –  when they want to see what happens when a cache item no longer exists
  2. For developers – to put to site admins some simple tool to reload data from Cache/Application . Just edit the LoadAll function to load only Cache/Application Winking smile
  3. For developers  – to test easily the session. Just delete ASP.NET_SessionId  cookie – you will get another one when you refresh the page.

You can view online at http://clearer.apphb.com/Clearer
The project could be found at http://clearer.codeplex.com and have all – source code, downloadable project .

Next week it will be a Nuget item.

For more features , please leave me a comment here or on codeplex at issues
Nuget package at http://nuget.org/packages/Clearer

Interfaces and more

 

Summary:

If you want common behavior, you need an interface. And from the first one is a small step to re-organizing the program.

Body:

When you make a component for other people, you must make the possibility for those to

1. customize your software with their software

2. provide a default implementation

For the messaging component, the first customization is to provide a way for the site using the messaging to use their users.

The first step is to create a custom project which can provide guidance to the users that want to implement. VS provides XML documentation –I have checked and put also “warnings as error”

clip_image002

Next , I have create the User interface:

/// <summary>
    /// the user that can send messages
    /// TODO version 2: make pagination
    /// </summary>
    /// <typeparam name="UserPrimaryKey">the type of primary key</typeparam>
    public interface IUser<UserPrimaryKey>
    {
        /// <summary>
        /// the user primary key
        /// </summary>
        UserPrimaryKey Key { get; set; }
        /// <summary>
        /// the user name to be displayed
        /// </summary>
        string UserNameToDisplay { get; set; }
        /// <summary>
        /// other info for the user
        /// </summary>
        string OtherInfo { get; set; }

        /// <summary>
        /// find friends
        /// </summary>
        /// <param name="search">find user by name</param>
        /// <returns></returns>
        IEnumerable<KVPNew<UserPrimaryKey, string>> FindFriends(string search);

        /// <summary>
        /// find friends online
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        IEnumerable<KVPNew<UserPrimaryKey, string>> FindFriendsOnline(string search);

        /// <summary>
        /// sends a message 
        /// </summary>
        /// <param name="message"></param>
        void SendMessage(IUserMessage<IUser<UserPrimaryKey>, UserPrimaryKey> message);

    }
 

Two methods are interesting : SendMessage and FindFriends

Let’s take first SendMessage. It was obviously clear that I need another interface – the message to be sent. So the next interface created:

/// <summary>
    /// the message to be sent to the user
    /// TODO version 2: allow messaging for more than 1 user
    /// TODO version 2: message importance
    /// </summary>
    /// <typeparam name="TheUser">user interface</typeparam>
    ///  /// <typeparam name="UserPrimaryKey">user primary key</typeparam>
    public interface IUserMessage<TheUser, UserPrimaryKey>
        where TheUser : IUser<UserPrimaryKey>
    {
        /// <summary>
        /// subject of the message
        /// </summary>
        string Subject { get; set; }
        /// <summary>
        /// body of the message
        /// </summary>
        string Body { get; set; }
        /// <summary>
        /// to the user
        /// </summary>
        TheUser To { get; set; }
        /// <summary>
        /// from the user
        /// </summary>
        TheUser From { get; set; }
        /// <summary>
        /// cc - as in email
        /// </summary>
        TheUser CC { get; set; }

        /// <summary>
        /// date of message
        /// </summary>
        DateTime DateInserted { get; set; }

        /// <summary>
        /// if recipient have read
        /// </summary>
        bool MessageRead { get; set; }
        // <summary>
        // bcc - as in email
        // </summary>
        //TheUser BCC { get; set; }



    }

Let’s take the other : IEnumerable<KVPNew<UserPrimaryKey, string>> FindFriends(string search);

It is clear that a user can send emails to friends( maybe to anybody if we make an intranet site for an enterprise) and I must somehow have the names and id’s of the friends. I could use KeyValuePair – but it is a struct and can not be compared with null . More, usually I need more data to be transferred – so I have created long ago a KVPNew class:

 /// <summary>
    /// this is the correspondent class of KeyValuePair structure from .net
    /// The features:
    /// 1. it is a class-  can be compared fastly with null
    /// 2. can be used in a search and display <paramref name="AdditionalData">AdditionalData </paramref>
    /// </summary>
    /// <typeparam name="TKEY">Key - it is compared in equals and GetHashCode</typeparam>
    /// <typeparam name="TValue">Value to be displayed</typeparam>
    public class KVPNew<TKEY, TValue>
    {
        public KVPNew() { }
        public KVPNew(TKEY key, TValue value):this()
        {
            this.Key = key;
            this.Value = value;

        }
        public TKEY Key { get; set; }
        public TValue Value { get; set; }
        public string AdditionalData { get; set; }
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            var o = obj as KVPNew<TKEY, TValue>;
            if (o == null)
                return false;
            return this.Key.Equals(o.Key);

        }
        public override int GetHashCode()
        {
            return this.Key.GetHashCode();
        }
    }

And, being to interfaces, I have created also an interface for admin people to find users

/// <summary>

/// used by application to load plugins to find users

/// because each application can have it’s own way to find users

/// <summary>
    /// used by application to load plugins to find users
    /// because each application can have it's own way to find users
    /// used by admins to find users
    /// Improvement version 2 : pagination 
    /// </summary>
    /// <typeparam name="T">user </typeparam>
    /// <typeparam name="UserKey">user key </typeparam>
    public interface IUsersFind<T,UserKey>
        where T:IUser<UserKey>
    {
        /// <summary>
        /// used to find users online to send message
        /// </summary>
        /// <param name="UserThatMakesTheSearch"> the user that makes the search </param>
        /// <param name="Search">search string - could be null</param>
        /// <returns> a list of users</returns>
        IEnumerable<KVPNew<T, string>> FindUsersOnline(T UserThatMakesTheSearch, string Search);
        /// <summary>
        /// used to find users (online or not )to send message
        /// </summary>
        /// <param name="UserThatMakesTheSearch"> the user that makes the search </param>
        /// <param name="Search">search string - could be null</param>
        /// <returns> a list of users</returns>
        IEnumerable<KVPNew<T, string>> FindUsers(T UserThatMakesTheSearch, string Search);
        /// <summary>
        /// find a user by his key
        /// </summary>
        /// <param name="key">the user key</param>
        /// <returns></returns>
        IUser<UserKey> FindUser(UserKey key);
            
    }


/// <summary>
    /// operations with the database
    /// </summary>
    /// <typeparam name="User"></typeparam>
    /// <typeparam name="UserPrimaryKey"></typeparam>
    public interface IUserList<User, UserPrimaryKey>: IDisposable
        where User : IUser<UserPrimaryKey>
    {
        /// <summary>
        /// fast delete all from database - good for testing
        /// </summary>
        void FastDeleteAll();
        
        /// <summary>
        /// add to internal list
        /// </summary>
        /// <param name="u">the user to be added </param>
        void Add(User u);
         
        /// <summary>
        /// save changes for new and old members
        /// </summary>
        void SaveNew();
        /// <summary>
        /// save changes for old members
        /// </summary>
        void SaveExisting();

        /// <summary>
        /// for retrieving 
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        User Find(int i);
        
    }

The final interfaces are in this picture:

clip_image004

Next time we will create the database EF4.1 files from DatabaseFirst and we will modify .tt templates to behave nicely with relationships.

Homework:

  • Add to IUserMessage a BCC field
  • What if To from IUserMessage will be directed to more than one person ?How do you implement it?
  • Do you think that is something missed from KVPNew class?( Hint == operator and GetHashCode)

Backup application for Windows Azure

I have written( with Vunvulea Radu and Catalin Gheorghiu)  a backup application for Azure. It is made with MVC + Azure Tables.

It was made initially for a contest, but I intend to work further and progress .

You can play at http://backupapp.cloudapp.net/

The code source is on http://myazurebackup.codeplex.com/ – and you can add also your feedback at http://myazurebackup.codeplex.com/workitem/list/advanced

And , if you are a programmer, you can also improve it – just leave a comment on codeplex!

Thank you,

MVC Zip Result

Sometimes you need to send to the user more than 1 file – or, maybe, the file is too large
The simplest way is : made a zip file that contains the others.

What do you need
1. SharpzipLib from http://www.icsharpcode.net/opensource/sharpziplib/ ( or download via NuGet in VS)
2. obtain the file(s) that you want as a string or as a byte[] – let’s say you have a byte[] to store in a str variable
3. make in your action something like that:

 var fcr = new ZipResult("Export.xls", str);
            fcr.AddFile("readme.txt","this zip file contains ..");
            return fcr;

4. copy the following code in your asp.net mvc projects:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Text;

namespace utilsResult
{
    public class ZipResult : FileResult
    {

        
        private Dictionary<string, byte[]> content = new Dictionary<string, byte[]>();
        public string FileNameZip;
        public ZipResult(string FileName, byte[] Contents)
            : base("application/octet-stream")
        {
            this.FileDownloadName = Path.GetFileNameWithoutExtension(FileName) + ".zip";
            AddFile(FileName, Contents);
        }
        public void AddFile(string FileName,  byte[] Contents)
        {
            content.Add(FileName, Contents);
        }
        public void AddFile(string FileName,string Contents, Encoding e = null)
        {
            if (e == null)
                e = ASCIIEncoding.ASCII;

            content.Add(FileName, e.GetBytes(Contents));
        }

        protected override void WriteFile(HttpResponseBase response)
        {

            using (ZipOutputStream zos = new ZipOutputStream(response.OutputStream))
            {
                zos.SetLevel(3);
                zos.UseZip64=UseZip64.Off;

                foreach (var item in content)
                {
                    ZipEntry ze = new ZipEntry(item.Key);
                    ze.DateTime = DateTime.Now;                    
                    zos.PutNextEntry(ze);
                    int count=item.Value.Length;
                    zos.Write(item.Value, 0, count);
                   
                    
                }                
            }
        }
    }
}

5. future improvements:
Zip the file(s) in a dll project to made fully testable!

ASP.NET MVC make users–roles fast

please left click on “Microsoft SQL Server Management Studio (push button)”
clip_image001
please create a database in “Microsoft SQL Server Management Studio”
clip_image002
please left click on “C:\Windows\system32\cmd.exe (push button)” and enter the following command : aspnet_regsql.exe -E -S .\SQLExpress -d proprii -A rm
clip_image003
please left click on “ListPanel (list)” in “Microsoft SQL Server Management Studio”
clip_image004
please left click on “Tables (outline item)” in “Microsoft SQL Server Management Studio”
clip_image005
please keyboard input in “Microsoft SQL Server Management Studio” [F5]
clip_image006
please right click on “aspnet_Applications (list item)” in “Microsoft SQL Server Management Studio”
clip_image007
please left click on “Select Top 1000 Rows (menu item)”
clip_image008
please left click in “Microsoft SQL Server Management Studio”
clip_image009
please left click on “aspnet_Users (list item)” in “Microsoft SQL Server Management Studio”
clip_image010
please right click on “aspnet_Users (list item)” in “Microsoft SQL Server Management Studio”
clip_image011
please left click on “Select Top 1000 Rows (menu item)”
clip_image012
please left click on “RdcDAL – Microsoft Visual Web Developer 2010 Express (Administrator) (push button)”
clip_image013
please edit web.config in your MVC application and change the connection string to point to your database
clip_image014
please scroll down until membership and change application name from / to /applicationName
clip_image015
please run your application and left click on “Log On (editable text)” in “Home Page – Windows Internet Explorer”
clip_image016
please left click on “User name (editable text)” in “Log On – Windows Internet Explorer”
clip_image017
please left click on “Register (editable text)” in “Log On – Windows Internet Explorer”
clip_image018
please left click on “User name (editable text)” in “Register – Windows Internet Explorer”
clip_image019
please input your details (I have put mine : ignatandrei)
clip_image020
please see that I am registered to the site
clip_image021
please verify to the database – left click on “Microsoft SQL Server Management Studio (push button)”
clip_image022
please left click in “Microsoft SQL Server Management Studio”
clip_image023
please press [F5] in “Microsoft SQL Server Management Studio”
clip_image024
please see the results – application name
clip_image025
please left click on “Execute (push button)” in “Microsoft SQL Server Management Studio” for the query that lists users.
clip_image026

Error intercepting in MVC when saving data

I have seen many times in MVC the following code , when doing a post and saving data :

try
{
        //code to save to database
}
catch
{
         ModelState.AddRuleViolations(TheModel.GetRuleViolations());
}

Why is not good ?
I will do a simple example : if some error occurs on the database level ( such as simple unique index on a name column ) or even some error occurs whenestablishing the database connection – you will never see what’s happening. And you will have no chance to repair the problem
A slighty better code is :

try
{
     ModelState.AddRuleViolations(TheModel.GetRuleViolations());
     if(ModelState.Count == 0)// no error in the model
     {
     //code to save to database
     }
}
catch(Exception ex)
{
      ModelState.AddModelError("", ex.Message);
}

Please see also how to do logging to the exception at
http://msprogrammer.serviciipeweb.ro/2010/04/19/logging-and-instrumentation/

A programmer day with “That assembly does not allow partially trusted callers”

I make a website, works on local IIS. Performs user registration  + uploading some zip files + generating custom feeds for those zip files.

Using SharpZipLib_0860_Bin ( to unzip file ) , StringTemplate.dll ( to perform custom feed generation ) and NUnit-2.5.7.10213 ( to perform tests).

So far ,so good. Moving into production . User registration works, upload works, trying feeds

“That assembly does not allow partially trusted callers”
Feeds were generated with StringTemplate- it was custom feeds ;-).

Searching , talking with hosting – seeing that this happens if your asp.net does not run under full trust , but under “Medium trust”.

Normally the provider does not want to change and send me advice to put AllowPartiallyTrustedCallersAttribute (APTCA) on the class:
http://msdn.microsoft.com/en-us/library/system.security.allowpartiallytrustedcallersattribute.aspx

This does not work without signing with a strong name – so I generate the snk file , sign mine assemblies, re-deploy. Same error:

“That assembly does not allow partially trusted callers”

That is normally and I have suspected – because I have to sign the stringtemplate, not mine dll.

Trying to see if the stringtemplate is signed  -it is! When put AllowPartiallyTrustedCallersAttribute  and trying to re-build – failed because I do not have his snk

Then, in disperation, I remove the snk from stringtemplate and re-make my project.

And now –

System.Security.SecurityException: Request failed.

Antlr.StringTemplate.FileSystemTemplateLoader.InternalLoadTemplateContents(String templateName) +0

That means that the files to read contents to generate feeds are not accesible to read. But, oh my dear .NET framework :could you not tell from the beginning ?

So, possible solutions to identify causes :  identify the assembly that  causes the harm and either

1. put a snk to this assembly and for all assemblies in superior chaining

2. remove the snk from this assembly

In either case, you should see what the error is.
So how I managed to solve ?
1. Put Reflector and dissasemble the source.
2. Re-compile without snk.
3. Put in Web.Config 4. Compile and run with debug
Now it stops at :
string templateText = InternalLoadTemplateContents(templateName);

This , in StringTemplate class, was

  protected override string InternalLoadTemplateContents(string templateName)
        {
            string templateText = null;
            string templateLocation = null;

            try
            {
                //templateLocation = Path.Combine(LocationRoot, GetLocationFromTemplateName(templateName));
                templateLocation = string.Format("{0}/{1}", LocationRoot, GetLocationFromTemplateName(templateName)).Replace('\\', '/');
                StreamReader br;
                try
                {
                    br = new StreamReader(templateLocation, encoding);
                }
                catch(FileNotFoundException)
                {
                    return null;
                }
                catch(DirectoryNotFoundException)
                {
                    return null;
                }
                catch(Exception ex)
                {
                    throw new TemplateLoadException("Cannot open template file: " + templateLocation, ex);
                }

                try 
                {
                    templateText = br.ReadToEnd();
                    if ((templateText != null) && (templateText.Length > 0))
                    {
                        //templateText = templateText.Trim();

                        if (filesWatcher == null)
                        {
                            filesWatcher = new FileSystemWatcher(LocationRoot, "*.st");
                            //filesWatcher.InternalBufferSize *= 2;
                            filesWatcher.NotifyFilter = 
                                NotifyFilters.LastWrite 
                                | NotifyFilters.Attributes
                                | NotifyFilters.Security 
                                | NotifyFilters.Size 
                                | NotifyFilters.CreationTime 
                                | NotifyFilters.DirectoryName 
                                | NotifyFilters.FileName;
                            filesWatcher.IncludeSubdirectories = true;
                            filesWatcher.Changed += new FileSystemEventHandler(OnChanged);
                            filesWatcher.Deleted += new FileSystemEventHandler(OnChanged);
                            filesWatcher.Created += new FileSystemEventHandler(OnChanged);
                            filesWatcher.Renamed += new RenamedEventHandler(OnRenamed);
                            filesWatcher.EnableRaisingEvents = true;
                        }
                    }
                    fileSet.Remove(templateLocation);
                }
                finally
                {
                    if (br != null) ((IDisposable)br).Dispose();
                    br = null;
                }
            }
            catch (ArgumentException ex) 
            {
                string message;
                if (templateText == null)
                    message = string.Format("Invalid file character encoding: {0}", encoding);
                else
                    message = string.Format("The location root '{0}' and/or the template name '{1}' is invalid.", LocationRoot, templateName);

                throw new TemplateLoadException(message, ex);
            }
            catch (IOException ex) 
            {
                throw new TemplateLoadException("Cannot close template file: " + templateLocation, ex);
            }
            return templateText;
        }

Does something ring a bell to you ?
Wait for an answer
Wait for an answer
Wait for an answer
Wait for an answer
Wait for an answer
Wait for an answer
Wait for an answer
Wait for an answer

Yes – FileSystemWatcher .
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
[IODescriptionAttribute(“FileSystemWatcherDesc”)]
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = “FullTrust”)]
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = “FullTrust”)]
public class FileSystemWatcher : Component,

Solution : Once defined my FileSystemTemplateLoader_MT – without FileSystemWatcher – all works well
So – the idea is : reflector, sources, find something strange. Remove, rebuild, re-test
(Thanks to OrcsWeb team for helping me on this problem !)

Five common mistakes for ASP.NET (MVC) accesing resources : css, js, images, ajax

To have once for all the link to show to people, because too much makes the same error again and again.

(From here – you can use ResolveUrl or Url.Content – it’s the same for me. I use ResolveUrl because I used first …)

Case 1 The image does not display

Please check you have the following :

<img src='<%= ResolveUrl("~/Content/images/YOURIMAGE.jpg" )%>'  alt="image" style="border:0" />

Case 2 The css does not show

Please check you have the following :

<%= string.Format("<link href='{0}' type='text/css' rel='stylesheet' />", ResolveUrl("~/Content/your.css")) %>

or

<style type="text/css">
@import '<%= ResolveUrl("~/Content/your.css") %>';

</style>

Case 3 The js does not execute (undefined error)

Please check you have the following :

<script type="text/javascript" src='<%= ResolveUrl("~/Scripts/yourjs.js")%>'></script>

Case 4 The js does execute in aspx page, but did not execute under js file

Please check you DO NOT have the following

<%

in the js file. The js file is not interpreted by the same engine as aspx, so can not interpret asp.net tags. Instead , add a parameter to your function : the path.

Simple example : Let’s say in aspx you have :

<script type=”text/javascript”>

function Generate(){

window.open(‘<% Url.Action(“About”)%>’);
}

</script>

and you call Generate();

When you put in .js file, please put this :

function Generate(url){

window.open(url);
}

and call like this :

Generate('<% Url.Action(“About”)%>');

Case 5 The ajax request gives you a 404 error.

Please ensure that you have

<%= ResolveUrl("~/path”)%>

and not

/path

Bonus 1: T4MVC , http://mvccontrib.codeplex.com/releases

Bonus 2: Edit the project file and put <MvcBuildViews>true</MvcBuildViews>

( short url: http://bit.ly/asp5Mistakes)

My standard way to work with dropdown box in ASP.NET MVC – 2 steps (or 3 if you want to add long description)

I have written a small post about dropdownlist template in ASP.NET MVC here : http://msprogrammer.serviciipeweb.ro/2010/05/30/mvc-helper-templates/

I think that the dropdownlist should be explained more – aand the example will be :

First, let’s say we have Employee and Department. And we have Employee that has a field, named IDDepartment.

When edit/create a user we want to display a dropdownlist for Department in order for the user to choose the department.

Step 1 : obtain from database a list of departments and transform into List<KeyValuePair<string,string>>  – where the first string is DepartmentID and the second is Department Name.

Let’s say there is a method to do that : deptList.Values

Step 2 : display into the aspx/ascx file with List_KVP template

<%: Html.EditorFor(model => model.deptList.Values, “List_KVP”, “IDDepartment”, new { SelectedValue = Model.emp.IDDepartment })%>

Here is the weak part: the “IDDepartment” is not strongly typed. You can transform that …but it requires writing another extension. However, when you modify the code for

SelectedValue = Model.emp.IDDepartment

it is right nearby…

For reference, here is the List_KVP.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<System.Collections.Generic.KeyValuePair<string,string>>>" %>
<%
    string Val = "",style="";
    if(ViewData.Values != null && ViewData.Values.Count > 0)
    {
        Val = (ViewData["SelectedValue"]??"").ToString();
        style = (ViewData["Style"] ?? "").ToString();
    }
    if (style.Length > 0)
    {

    }
    var id=ViewData.TemplateInfo.GetFullHtmlFieldId("") ;
    id = id + "";
    %>

<select id="<%:id %>" name="<%:ViewData.TemplateInfo.GetFullHtmlFieldName("") %>" style="<%: style %>">
    <% foreach (var val in Model)
       { %>
            <option  value='<%: val.Key %>' <%:(val.Key == Val)?"selected=selected":"" %>><%: val.Value %></option>
    <%} %>
</select>
<% if(Model.Exists(x=>x.Key ==Val) )
{
       %>
       <script type="text/javascript">
   $(document).ready(function () {

       $('#<%:id  %>').change();
   }     );
      </script>
      <%
}
    %>

Oh, and if you ask how to add a description , nothing more simple :
Step1 : add to dropdown an onchange event : onchange=’javascript:funcDepartmentRetrieve(this)”
Step 2: create a java script function that retrieves the long description from the id

 <script type="text/javascript">
         <%: Html.JavaScriptFind( Model.deptList.LongDescriptionValues, "funcDepartmentLong","notfoundDepartment") %>
        </script>
  

Step 3 : Mix the 2 javascript functions

For your reference, the code for JavaScriptFind is

 public static MvcHtmlString JavaScriptFind(this HtmlHelper hh, ICollection<KeyValuePair<string,string>> values, string Name, string NotFound)
        {
            string s = "function " + Name + "(value){  switch(value){";
            string ret = "case '{0}' : return '{1}';" + Environment.NewLine;
            foreach (var item in values)
            {
                //TODO : compensate for '
                s += string.Format(ret, item.Key, item.Value);
            };
            s += string.Format("default : return '{0}' ;//+ value;"  + Environment.NewLine, NotFound);
            s += "};";//switch
            s += "}";//function
            return MvcHtmlString.Create(s);
        }

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.