Category: ASP.NET MVC

Chosen and Jquery and MVC

In the MVC forums I have seen a reference to Chosen. From the description here:
“Chosen is a JavaScript plugin that makes long, unwieldy select boxes much more user-friendly.”
It look beautifool – and I see the opportunity to improve my toolbox. I said: “I will do in 10 minutes”. Well, it did take longer – but not so long.

I will make an example my tutorial mvc and ajax – since it does not require any database.

So I download the source from https://github.com/harvesthq/chosen/ , put the .js in Scripts folder, the .css in Contents folder and registered in JqueryMVCRazor\JqueryMVCRazor_Web\Views\Shared\_Layout.cshtml

<link href="@Url.Content("~/Content/chosen.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/chosen.jquery.min.js")" type="text/javascript"></script>

Here is the code : ( from JqueryMVCRazor\JqueryMVCRazor_Web\Views\Shared\EditorTemplates\EditEmployeeViewModel.cshtml ):

 @{
     var idcombo = "#"+ ViewData.TemplateInfo.GetFullHtmlFieldId("cmbemp" + Model.Employee.IdEmployee);
     }<script>
     $(document).ready(function () {

         $("@idcombo").chosen({ no_results_text: "No results matched"});

     });

 </script>

And I said, this will be all.

Not so: see the picture – the names does not show up:

image

First I was thinking that it does not select the item. After several attempts, I realize the “…” ( three dots) – that means the width was not enough.
Next move, since I was in the javascript mood, was to add some javascript to adjust the width to fit:

So the code becomes:

$("@idcombo").chosen({ no_results_text: "No results matched" });
$("@idcombo").width("350");

No difference. So I tried the opposite way:

$("@idcombo").width("350");
$("@idcombo").chosen({ no_results_text: "No results matched" });

Now it matches:
image

And , thinking about a bit, it is better right in the Dropdown declaration :

@Html.DropDownList("cmbemp" + Model.Employee.IdEmployee, new SelectList(Model.DepartmentList, "IDDepartment", "NameDepartment", Model.Employee.Department.IdDepartment),new{ style="width:350px;"})

Summary:

Integration of Chosen with MVC dropdown is rather simple. Add the .js, the .css, register in the page, add $(“@idcombo”).chosen() declaration and do not forget the width of the dropdown ( select )

Source code here
Later edit: Please add also

to the header

First version of Messaging system

image

Realized the first version. When you logon on the system, the application sends you an email and you can see it.

Lots of thing done – however, the testing is not complete.

Logging was the difficult part- since I want to work with various loggers( LOG4NET, NLOG, MS TRACE, and so on). I required to a duck typing from  DeftTech. See logging assembly for more details.

You can download the files from http://messagemvc.codeplex.com/– however, you may want to wait for a NuGET version.

If you want to help me further , please send me an email via http://messagemvc.codeplex.com/.

Jquery Ajax Request and MVC detailed

I have made a post about how to configure the MVC with Razor , Partial View and returning JSON.  It does not need a database – that also because it should be simple to download and see the mechanism.

The sample demonstrates:

  1. Cascading dropdown ( see the button Populate from action and Cascading drop down)
  2. Populating a table from a Partial View(see the button Add New Employee(jquery call action and render)
  3. How to handle  error from action ( press Save 2 )
  4. How to send id parameters (long) from javascript to action ( press Delete 1 or Delete 2)
  5. How to send objects(Employee) from javascript to action ( press Save 1 or Save 2)

The PartialView is made with Razor – but this does not matter. The project can be written as well in ASPX.
asp.net mvc jquery razor cascading demo

I think that a featured programmer will understand fast the code . Now it’s the time for the beginner programmer.

Principles:

  1. Ajax Request in the server should return true or false – never return  error. The error should come from network failure or incorrect IIS server communication.
  2. Cascading dropdowns: return a list and populate the dropdown in the request.
  3. To send only id – as in the url, put {. To send more data , use JSON.Stringify
  4. Returning PartialViews with data : the most easy way is to create an Action , send the data  to this action and return a Partial View. The attempt to re-do the data from an existing DOM Element in javascript is error prone.
  5. A View page must have a ViewModel ( named Model in MVC code ) . The ViewModel can contain data from multiple classes in order to have all data that the View needs. How do you construct this ViewModel ? Simple: think about the data the View needs.

Exemplification :

1.Ajax Request in the server should return true or false – never return  error.

The _Layout in MVC should contain this :

$(document).ready(function () {
            $.ajaxSetup({
                cache: false,
                error: function (x, e) {
                    if (x.status == 0) {
                        alert('You are offline!!\n Please Check Your Network.');
                    } else if (x.status == 404) {
                        alert('Requested URL not found.');
                    } else if (x.status == 500) {
                        alert('Internal Server Error.');
                    } else if (e == 'parsererror') {
                        alert('Error.\nParsing JSON Request failed.');
                    } else if (e == 'timeout') {
                        alert('Request Time out.');
                    } else {
                        alert('Unknown Error.\n' + x.responseText);
                    }
                }
            });
        });

See as the JSON error are handled here – network, timeout, others. And in the server never return error – use this boilerplate

 [HttpPost]
        public JSonResult ....
        {
             try
            {
             var data = obtain data from the server....
   return Json(new {ok = true,mydata=data,  message = ""});
            }
            catch (Exception ex)
            {
                return Json(new {ok = false, message = ex.Message});
            }

This way, the only code returned is ok – false or true.
The javascript that call this have this form

 $.ajax({
            type:"POST",
            url:...  ,
            data: .... ,
            datatype:"JSON",
            contentType:"application/json; charset=utf-8",
            success: function (returndata) {
                if (returndata.ok) {
                    //do something with returndata.mydata
                }
                else {
//this is an error from the server
                    window.alert(' error : ' + returndata.message);
                }

            }
        }
        );

See tha handling of if (returndata.ok)
2.Cascading dropdowns: return a list and populate the dropdown in the request.

Example in code: from an department id in the first dropdown the code will fill the employees for the department
Always begin with server code .

[HttpPost]
        public JsonResult GetEmployeesForDepartment(long id)
        {
            try
            {
                //in real application made a better load / retrieving
                var emp = new employeeList();
                emp.Load();
                emp.RemoveAll(item => item.iddepartament != id);
                
                return Json(new { ok = true, data = emp, message = "ok" });
            }
            catch (Exception ex)
            {
                return Json(new { ok = false, message = ex.Message });
            }
        }

As you the first principle ( handle errors ) is applied and the data is filled and returned by

return Json(new { ok = true, data = emp, message = “ok” });

Then wrote an event( here cascadingdropdown) for the first dropdown

<select id="cmbDept" style="display:none" onchange="javascript:cascadingdropdown()"> 
</select>

Then code it

 function cascadingdropdown() {
        var idDept = $("#cmbDept").val();
        window.alert(" call cascading dropdown for iddepartment = " + idDept);
        var urlemp = '@Url.Action("GetEmployeesForDepartment")';
        var select = $('#cmbEmp');
        $.ajax({
            type: "POST",
            url: urlemp,
            data: { id: idDept },
            success: function (returndata) {
                if (returndata.ok) {

                    window.alert('employee data is on javascript,  populating combo ');
//empty the combo
                    select.empty();
//fill again 
                    $.each(returndata.data, function (index, itemData) {

                       
                        select.append($('<option></option>').val(itemData.IdEmployee).html(itemData.NameEmployee));


                    });
                    select.show('slow');
                }
                else {
                    window.alert(' error : ' + returndata.message);
                }

            }
        }
        );

    }

The filling of the second dropdown occurs on
$.each(returndata.data, function (index, itemData) {
3. To send only id – as in the url, put {. To send more data , use JSON.Stringify
The code is when you press “Save” or “Delete” . For saving we should send the Name and the department id. For Delete , just the id.
Let’s begin with delete
In server code delete Action have only the id of the employee as a parameter:

    public ActionResult DeleteEmployee(int id)
        {
//just delete it - not important code

So the client code will be simple:

function deleteEmployee(idemployee){
        window.alert('now delete ' + idemployee);
        var urlDelete = '@Url.Action("DeleteEmployee")';
        $.post(urlDelete,
            {id: idemployee}, // see here how we transmit an unique parameter
         function (returndata) 
         {
            if(returndata.ok){
                window.alert(' deleted!');
                $("#emp"+ idemployee).hide('slow');
            }
            else{
                window.alert(' error : ' + returndata.message);                
            }

        });

So you see how the
DeleteEmployee(int id)
from server code correspond with
{id: idemployee}
from the client browser.

For saving an employee we will be happy to receive the Employee class:

[HttpPost]
        public ActionResult SaveEmployee(employee emp)
        {

To receive such a parameter we will replicate employee structure in Javascript

function saveEmployee(idemployee) {
        window.alert('now save ' + idemployee);
        var urlSave= '@Url.Action("SaveEmployee")';
        var dept = $("#item_cmbemp" + idemployee).val();
        var name = $("#txtemp" + idemployee).val();
        //replicated structure as the emnployee class in server C# code
        var emp = {
            IdEmployee: idemployee,
            NameEmployee: name,
            iddepartament: dept
        };
        $.ajax({
            type:"POST",
            url:urlSave,
            data:JSON.stringify(emp),//use this in order to MVC binding to take place 
            datatype:"JSON",
            contentType:"application/json; charset=utf-8",
            success: function (returndata) {
                if (returndata.ok) {
                    window.alert(' saved ');                    
                }
                else {
                    window.alert(' error : ' + returndata.message);
                }

            }
        }
        );

    }

So you see how the class instance parameter <strong>emp from server
SaveEmployee(employee emp)
corresponds with the client browser emp structure that is stringified to send to the server

 var emp = {
            IdEmployee: idemployee,
            NameEmployee: name,
            iddepartament: dept
        };

4. Returning PartialViews with data :
Use the same Partial View that you use it for rendering an edit.

public ActionResult AddNewEmployee()
        {
            
            EditEmployeeViewModel evm = new EditEmployeeViewModel();
            evm.DepartmentList = new departmentList();
            evm.DepartmentList.Load();
            evm.Employee = new employee(0,"New !",evm.DepartmentList[0]);
            return PartialView("~/Views/Shared/EditorTemplates/EditEmployeeViewModel.cshtml", evm);//TODO: use T4MVC
        }

And javascript code:

 function AddNew() {
        var urlAdd='@Url.Action("AddNewEmployee")';
        $.get(urlAdd, function (data) {
            window.alert(' new employee coming from action !');           
            $('#tableEmp > tbody:last').after( data);//add last the whole data
        });


    }

We are using a simple get – and we have “cached” to false ( see rule 1)

4. A View page must have a ViewModel ( named Model in MVC code ) . The ViewModel can contain data from multiple classes in order to have all data that the View needs
Look at the page
asp.net mvc jquery razor cascading demo

It is clear we need the list of department( maybe cached somehow to not query all the time the database) and the employee (id, name) for each row of the table .
So this we will make:

  public class EditEmployeeViewModel
    {
        public departmentList DepartmentList{get;set;}//need the list to put in dropdown
        public employee Employee { get; set; }// the editing employee
        public EditEmployeeViewModel()
        {
            
        }
        public EditEmployeeViewModel(int id)
        {
            DepartmentList = new departmentList();
            DepartmentList.Load();
            var EmployeeList = new employeeList();
            Employee=EmployeeList.LoadId(id);
        }
         
    }

Conclusion

  1. Ajax Request in the server should return true or false – never return error.
  2. Cascading dropdowns: return a list and populate the dropdown in the request.
  3. To send only id – as in the url, put {. To send more data , use JSON.Stringify
  4. Returning PartialViews with data : the most easy way is to create an Action , send the data to this action and return a Partial View.
  5. A View page must have a ViewModel ( named Model in MVC code ) . The ViewModel can contain data from multiple classes in order to have all data that the View needs.

The download is here:
Jquery MVC Razor demo full

Differences MVC versus WebForms

Rule of thumb for differences between ASP.NET MVC versus ASP.NET WebForms 1 :

  1. If it is a Web Form Control ( asp:textbox, asp:gridview) it does not work in MVC. Period. 2. Use DisplayTemplates/EditorTemplates/PartialView/HtmlHelpers and some jquery (or your favorite javascript framework) magic. See http://msprogrammer.serviciipeweb.ro/2010/05/30/mvc-helper-templates .3
  2. Security is NOT on web.config ( location ). Security is on Actions. ( Authorize or derive from ). However, enforce your Repository /Business Layer for security. Do not rely unique on Web security.
  3. Anything else it works in MVC like in WebForms . ( it means Session, Cache, Application, Cookies , IIS and so on)1. However, please note that MVC have TempData, ViewData, Filters, Models4 , ModelBinders4 and more features . Please learn those as they are important to MVC.

Notes:
1 : I am not using anymore WebForms. Too troublesome getting all those events. And which order it is when Ajax comes in action?! And I can tell you another 1000 reasons. But please follow tutorials from http://www.asp.net/mvc

2 : Ok, ok, it might work on display on HttpGet. But on HttpPost in 99,99% cases no.And no events. And will be more troublesome than advantages! So basic instinct: NO WEB FORMS CONTROLS ON ASP.NET MVC!

3No, the login controls are not available in MVC. Did you take a chance to see the default source code for a new MVC template ? There are controller and partial views implemented. Even remote validations! (Please follow tutorials from http://www.asp.net/mvc)

4 Ok, ok,so ASP.NET vNext will have strongly typed Models on controls.  And a ModelBinding over ValueProviders ( see [QueryString] on this post ) . But see note 1

Implementations GUI details

When creating a GUI you must think to give user some good feeling about what the software can do – so I started to MVC 4 website, that have mobile support integrated.

More, you must demonstrate some features right away to the user – so what’s best if not a message from system admin to the user  to “welcome” him ?

For this , I have to  implement a template with RazorEngine – simple to used from his code

string template = "Hello @Model.Name! Welcome to Razor!";
  string result = Razor.Parse(template, new { Name = "World" });

Summary of modifications for this simple operation – send and display a message  from Admin when a user registers

  1. Add connectionstrings to web.config – to connect to database + SiteUtils static class to retrieve it.
  2. RegisterAdmin user in Application_Start – in order to have user Admin in the database ( generate a GUID and put into a const)
  3. Add “welcome.txt” file
  4. Add RazorEngine to parse message
  5. Modify  Register action in order to send message after a user registers
  6. Add an area “Messaging” in order to can have the messaging separated from main site( to be easier to xcopy)
  7. Add an Index action( display read/unread messages) + View
  8. Add an DisplayMessage action (display a message) + View

All for this picture where it shows number of unread messages(1) and list :

image

You will find code at http://messagemvc.codeplex.com/SourceControl/changeset/changes/81924

Homework:

Think about the user actions . He will be interested in the following for existing messages:

  1. Unread messages
  2. View of all messages (paginating)
  3. Search messages:
    • Messages from a date
    • Messages from someone
    • Search

What do you think it will be done for implementing those?

Creating Edmx files and testing

The favorite ORM in .NET world for me it is edmx files. It gives you the database plain – and have generators for POCO (http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx) as for EF4.1 DBContext(http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-model-amp-database-first-walkthrough.aspx).

I will use this one – because of the new ! But the template is over simplistic  -so I improved . I do not want you to bother you with my experience – I want to say that, after playing with Data attributes – I decide that Fluent Configuration suits all. The template is here:

DBContext-SecondVersion.zip

 

For example, the default template

Also for testing I use the fact the default EF4.1  Model1.Context.tt generates this code:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

( see playing on safe side to NOT drop the existing database?!)

Mine Model1.Context.tt generates this:


 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
    		var prefix = System.Configuration.ConfigurationManager.AppSettings["prefixTable"]??"";
    		bool Continue=true;
            OnBeginModelCreating(modelBuilder,prefix, ref Continue);
    		if(!Continue)
    			return;
    
    		//construct default
    		#region smsg_Message 
    		modelBuilder.Entity<smsg_Message>().ToTable(prefix  + "smsg_Message");
    		modelBuilder.Entity<smsg_Message>().HasKey(item => item.IDMessage);
    
    
    		#endregion
    		#region smsg_Message_Archive 
    		modelBuilder.Entity<smsg_Message_Archive>().ToTable(prefix  + "smsg_Message_Archive");
    		modelBuilder.Entity<smsg_Message_Archive>().HasKey(item => item.IDMessageArchive);
    
    
    		#endregion
    		#region smsg_MessageThread 
    		modelBuilder.Entity<smsg_MessageThread>().ToTable(prefix  + "smsg_MessageThread");
    		modelBuilder.Entity<smsg_MessageThread>().HasKey(item => item.IDMessageThread);
    
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessage_IDMessageInitial)
                    .WithMany(u => u.IDMessage_IDMessageInitial)
                    .HasForeignKey(x => x.IDMessageInitial)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessage_IDMessageReply)
                    .WithMany(u => u.IDMessage_IDMessageReply)
                    .HasForeignKey(x => x.IDMessageReply)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessageArchive_IDMessageInitial)
                    .WithMany(u => u.IDMessageArchive_IDMessageInitial)
                    .HasForeignKey(x => x.IDMessageInitial)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessageArchive_IDMessageReply)
                    .WithMany(u => u.IDMessageArchive_IDMessageReply)
                    .HasForeignKey(x => x.IDMessageReply)
                    .WillCascadeOnDelete(false);
    
    		
    
    		#endregion
    	
    		OnFinishModelCreating(modelBuilder, prefix);
    		
        }

More, for giving you a smell of what the templates generates, look at this function for reading messages sent:


 public  IEnumerable<IUserMessage<IUser<String>,string>> RetrieveMessageSent(DateTime dt)
        {
            using (smsg_Message_List ml = new smsg_Message_List(ConnectionMessaging))
            {
                ml.LoadFromDB.AddToCustomPredicate(smsg_Message_FindDB.fexp_FromUser(this.Key));
                ml.LoadFromDB.AddToCustomPredicate(smsg_Message_FindDB.fexp_DateInsertedBetweenEqDate(dt, dt));
                ml.LoadFromDB.LoadFindCustomPredicate();
                return ml;
            }
        }

The class smsg_Message_List and the AddToCustomPredicate , LoadFindCustomPredicate and the expression fexp_FromUser and fexp_DateInsertedBetweenEqDate are automatically generated by the template.
I do not think that the template is perfect – it just helps me a lot!

For the database tests, I was thinking of NUnit – but was deprecated by xUnit. It has a nice project, named SpecificationExample – and it generates data in BDD style .
For example, this code:


 public void CreateUsersAndSendMessage()
        {
            
            List<SimpleUser> users = null;

            "When create two users".Context(() => users = CreateUsersAndDeleteItFirst());
            "it will be friends".Assert(() => FindFriend(users).ShouldNotBeNull());
            
            "and when send message from first user to second user".Do(() => SendMessage(users));

            
            "we will retrieve it searching message from first user ".Assert(() => RetrieveMessageSent( users[0]).ShouldEqual(1));

            "we will NOT retrieve it searching message from second user".Assert(() => RetrieveMessageSent(users[1]).ShouldEqual(0));

            "we will retrieve searching messages received by second user".Assert(() => RetrieveMessageReceived(users[1]).ShouldEqual(1));

            "we will retrieve count of unread messages :1 ".Assert(() => RetrieveMessageUnreadCount(users[1]).ShouldEqual(1));

            


        }

run by this command:

xunit.console.clr4.x86.exe "$(TargetPath)" /html "$(TargetDir)a.html" 

in Build events it will generate the following HTML


————————————————————————

✔  When create two users and when send message from first user to second user, it will be friends

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.060s

✔  When create two users and when send message from first user to second user, we will NOT retrieve it searching message from second user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.099s

✔  When create two users and when send message from first user to second user, we will retrieve count of unread messages :1

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.032s

✔  When create two users and when send message from first user to second user, we will retrieve it searching message from first user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.053s

✔  When create two users and when send message from first user to second user, we will retrieve searching messages received by second user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

—————————————–


Nice , isn’t it?

Homework :
1. use the ITLIst.tt template , search for

//TODO: prefix

and make generating same prefix for the table as in the Model1.Context.tt( search prefix)
( Do not forget the change the edmx file name in the .tt file!)
2. Make a .t4 file to share commonalities( such as edmx name)

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)

Simple messaging system -database configuration

Contents
We will create the database tables and user to access the database from the application
You will find at bottom the

  1. scripts for creating database
  2. materials to read further
  3. homework for you

As an older database programmer, I have started with database configuration.

The selected database engine is Sql Server 2008 R2 Express – the free version that can be downloaded from here : http://www.microsoft.com/express
To create tables , just start Sql Server Management Studio, point to your database, right click “Tables” node and press “New Table”
I have created the following tables in the diagram:

image

Several comments:

  1. The smsg_User table can ( and will !) be replaced by the owner of the site with his table of users . More, this will be configurable by the owner. That’s why I choose IDUser being varchar(150) – maybe the user id will be GUID ?
  2. The messages are stored in the smsg_Message
  3. The message archive table(smsg_Message_Archive) is simply to make the search faster on smsg_Message table. We will put here the messages older than (1 month? 2 months?)
  4. The smsg_MessageThread contains the possibility for the user to reply more than one time to a message.
  5. IDMessage is bigint . We can also put guid to have unlimited number of messages -but 9,223,372,036,854,775,807 messages ( * 2 -we will see it in action) will be enough for a small site.
  6. You can download the script from here:
    http://msprogrammer.serviciipeweb.ro/wp-content/uploads/MVC-4_94F/smsgV1.zip

Also you should not rely on Windows Identity to access the database. Why ? Because , usually , on Web hosting you have only some user name and password for database – not Active Directory user.

We will create an user that can access the Database and have full rights. We will manage further the rights for everyone.

Open SQL Server Management Studio and go to Security.

Please right click on “Logins ” in “Microsoft SQL Server Management Studio”
clip_image001[4]
Step 2: Please left click on “New Login… “
clip_image002[4]
Step 3: Please introduce “smsg” in “Login – New”
clip_image003[4]
Step 4: Please left click on “SQL Server authentication ” in “Login – New”
clip_image004[4]
Step 5: Please left click on “Password ” in “Login – New”
clip_image005[4]
Step 6: Please put “smsg” in “Login – New”
clip_image006[4]
Step 7: Please “smsg” in “Login – New” for confirm password
clip_image007[4]
Step 8: Please left click in “Login – New”
clip_image008[4]
Step 9: Please left click on “Enforce password policy ” in “Login – New”
clip_image009[4]
Step 10: Please left click on “Database ” in “Login – New”
clip_image010[4]
Step 11: Please keyboard input in “Login – New” […]
clip_image012[4]
Step 12: Add rights : Please left click on “SMsgS “
clip_image013[4]
Step 13: Please left click on “User Mapping ” in “Login – New”
clip_image014[4]
Step 15: Please mouse drag end on “Current view pane ” in “Login – New”
clip_image015[4]
Step 16: Please left click on “Smsg” database
clip_image016[4]
Step 17: smsg user will be in the dbo schema
clip_image017[4]
Step 18: Please put “dbo” as schema
clip_image018[4]
Step 19: Please select “db_datareader “
clip_image019[4]
Step 20: Please select on “db_datawriter ” in “Login – New”
clip_image020[4]
Step 21: Please select “db_owner ” in “Login – New”
clip_image021[4]
Step 22: Please left click on “OK ” in “Login – New”
clip_image022[4]
Now we will verify on database:
Step 23: Please left click on “Object Explorer Hierarchy ” in “Microsoft SQL Server Management Studio”
clip_image023[4]
Step 24: Please left click on “Object Explorer Hierarchy ” in “Microsoft SQL Server Management Studio”
clip_image024[4]
Step 25: Please left click on “smsg ” in “Microsoft SQL Server Management Studio”
clip_image025[4]

Summary
We have created database tables . We also generate a script for you that can be found here:
http://msprogrammer.serviciipeweb.ro/wp-content/uploads/MVC-4_94F/smsgV1.zip

But the security login ( user : smsg , pwd: smsg) you do have to do yourself.
You can also download the database backup from http://messagemvc.codeplex.com/releases/view/74250

To read:
3 Normal Form from Database Normalization, http://en.wikipedia.org/wiki/Database_normalization

Homework:
What if we want to send messages to a further date( let’s say, after on day 1 on the next month) ? What database changes do you envision ?

MVC4 and Simple messaging system

 

MVC4  Developer preview with mobile support just released. And, because best way to deal with is within an application, I decide to create a simple messaging system for any site that is made with MVC.

Description:

I begin with a registered user. What he can do:

1. Create messages ( subject + body ) to send to another registered user. The list of the users on the system will be taken either from database, either from an Application variable. The message will be recorded to a database( configured by the owner of the site )  with the possibility to be send also by email

2. When login, the registered user can see the list of messages and replies send to/by him. Also, if he has unread messages he can see an advertisement.

3. The application could be seen also from a mobile device.

What should be done also:

4. The install of the application should be easy for any developer ( xcopy or some package – like Nuget or recipe)

Wish me luck to finish !

Asp.NET MVC, Jquery and Razor – Cascading dropdown, retrieving partial views, Json send objects, handling errors

There are many blogs and other posts on using jQuery with MVC. You can find individual posts on:

·         How to send objects to an action method via JavaScript.

·         How to retrieve partial views.

·         How to handle errors.

asp.net mvc jquery razor cascading demo

I have written a sample showing how to do all of these together. The sample is written in  MVC 3 using Razor views

The sample demonstrates:

  1. Cascading dropdown ( see the button Populate from action and Cascading drop down)
  2. Populating a table from a Partial View(see the button Add New Employee(jquery call action and render)
  3. How to handle  error from action ( press Save 2 )
  4. How to send id parameters (long) from javascript to action ( press Delete 1 or Delete 2)
  5. How to send objects(Employee) from javascript to action ( press Save 1 or Save 2)

Without further ado, this is the project . Enjoy!

Jquery MVC Razor demo full

PS: If you seems that the code is too hard, here is a more detailed explanation :http://msprogrammer.serviciipeweb.ro/2011/12/05/jquery-ajax-request-and-mvcdetailed/

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.