Xceedas

Xceedas
xceedas

Monday, 22 September 2014

Handling Concurrency in MVC and EF

This article shows how to handle concurrency in MVC and EF. I am assuming that you have some idea of the Fluent API.
Concurrency Issue
 
It is an important issue in real-world development. The webs we develop are used by thousands of users. Concurrency occurs when two users want to modify/delete the same entity at the same time. In other words, suppose user B wants to update the entity before the user A committed the change he made to that same user. If you don't handle the situation only whoever commits last, that update will be reflected. In my applications this risk is non-critical and okay for the requirements perspective. In that case you need not to bother about this issue. But some projects really want to handle the concurrency issues.
 
Optimistic Concurrency
 
We can implement concurrency in two ways. Pessimistic Concurrency (Locking) and Optimistic Concurrency. Pessimistic Concurrency deals with database locking and is out of context for this article since it is more specific to Windows applications. We will see what Optimistic Concurrency is.
 
From Wikipedia the definition of Optimistic Concurrency is:
 
"Optimistic concurrency is a concurrency method that assumes that multiple transactions can complete without affecting each other and that therefore transactions can proceed without locking the data resources that they affect. Before committing, each transaction verifies that no other transaction has modified its data. If the check reveals conflicting modifications, the committing transaction rolls back."
 
Implementation
 
There can be various approaches available for concurrency handling. The procedure used most is known as a Store Wins scenario. In this approach we prevent user B's change being updated in the database. Typically user B will receive an error message showing him/her the current state of the data and allow him/her to reapply the change if he/she really wants to make the change.
 
Step 1
 
Include a tracking column that can be used to determine when the row is changed. The datatype of this tracking column is generally rowversion. If the user writes an Update or Delete command then the where clause will include the original version of that column. If the row being updated has been changed by another user, the value in the rowversion column is different from the original value, then the statement will not find the row to update/delete and is interpreted as a concurrency conflict.
 
Step 2

In your model class add a property: 
  1. [Timestamp]  
  2. public byte[] RowVersion { get; set; }  
The Timestamp attribute specifies that this column will be included in the Where clause of Update and Delete commands.
 
Step 3
 
Set the Concurrency token in the model builder: 
  1. modelBuilder.Entity<YourEntityName>()  
  2. Property(p => p.RowVersion).IsConcurrencyToken();  
Update the database from the Package Manager Console (PMC).
 
Step 4
 
Now if the concurrency conflict occurs then the update/delete statement will generate a DbUpdateConcurrencyException. So we need to handle this exception and show the appropriate something.
  1. catch (DbUpdateConcurrencyException ex)  
  2. {  
  3.     var entity= ex.Entries.Single().GetDatabaseValues();  
  4.     if (entity == null)  
  5.     {  
  6.          ModelState.AddModelError(string.Empty,  
  7.             "Unable to save changes. The entity you are trying to update was deleted by another user.");  
  8.     }  
  9.     else  
  10.     {  
  11.          ModelState.AddModelError(string.Empty, “ The record you want to edit has been updated by another user. If you still want to make the change then click the “Save” button again. Otherwise click the back button to discard!”);  
  12.         MyEntity.RowVersion = (MyEntity)databaseEntry.ToObject().RowVersion;  
  13.     }  
  14. }  
Step 5
 
The view will store the original RowVersion value in a hidden field as in the following:
  1. @Html.HiddenFor(model => model.RowVersion)  

Convert Decimal To Roman using Dictionary

  1. namespace CSharpPractice  
  2. {  
  3.     class Class1  
  4.     {  
  5.         public static void RomanDecimalConvertor(int num)  
  6.         {  
  7.             Dictionary<int, string> roman = new Dictionary<int, string>  
  8.                                                             {  
  9.                                                              {1,"I"}, {4,"IV"},  
  10.                                                              {5,"V"}, {9,"IX"},  
  11.                                                              {10,"X"}, {40,"XL"},  
  12.                                                              {50,"L"}, {90,"XC"},  
  13.                                                              {100,"C"}, {400,"CD"},  
  14.                                                              {500,"D"}, {900,"CM"},  
  15.                                                              {1000,"M"}  
  16.                                                             };  
  17.             int divisor = 0, times = 0;  
  18.             while(num!=0)  
  19.             {  
  20.                   
  21.                 foreach (int key in roman.Keys)  
  22.                 {  
  23.                     if (key > num)  
  24.                         break;  
  25.                     divisor = key;  
  26.                 }  
  27.                 times = num / divisor;  
  28.                 for (int i = 1; i <= times; i++)  
  29.                 {  
  30.                     Console.Write(roman[divisor]);  
  31.                 }  
  32.                 num = num % divisor;  
  33.                  
  34.             }  
  35.         }  
  36.     }  
  37. }  
  38.   
  39.   
  40.   
  41. namespace CSharpPractice  
  42. {  
  43.     class Program  
  44.     {  
  45.         static void Main(string[] args)  
  46.         {  
  47.             Class1.RomanDecimalConvertor(1500);  
  48.             Console.Read();  
  49.         }  
  50.     }  
  51. }  

Display Country List Without Database in ASP.Net C#

Use the following source code in the default.aspx <body> section page as: 

<body>
    <form id="form1" runat="server">
    <div class="div" align="center">
    <br /> <br />
        <asp:DropDownList ID="DropDownList1" runat="server" Width="100px">
        </asp:DropDownList>
    </div>
    </form>
</body>

Then switch to view code and create the following method in the default.aspx.cs to get the country list using Globalization:
countrylistMethod.png

Now call the preceding method on page load with the dropdonlist to bind the country list as:
CallingMethod.png

Sunday, 21 September 2014

Getting Comment Count Based on URL


In one of our news listing web part we have requirement to show the comments count for given news. On news pages we are using the NoteBoard web part for commenting purpose.

For news listing we are using OOB Content by Search (CBS) web part and in front of news title we need to show the comment count.

Since we are using OOB web part we don’t have an option of code where we can create SocialCommentManager class and call GetCount(Uri) method. The other option is to use the SocialDataService (SocialDataService.asmx) and call this from the display template of CBS web part. This solution is also compatible with Office 365.

Following is the sample script:
  1. function ReturnCommentsCount(url) {   
  2.      var dataXML = GenerateDataXML([url]);   
  3.      $.ajax({   
  4.          url: "/_vti_bin/SocialDataService.asmx?op=CountCommentsOnUrl",   
  5.          data: dataXML,   
  6.          type: "POST",   
  7.          async: true,   
  8.          complete: processResult,   
  9.          contentType: "text/xml; charset=utf-8",   
  10.          dataType: "xml"   
  11.      })   
  12.    
  13.      //Following function generates the require soap XML   
  14.      function GenerateDataXML (url) {   
  15.          var soapXml = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +   
  16.          "<soap:Body>" +   
  17.          "<CountCommentsOnUrl xmlns=\"http://microsoft.com/webservices/SharePointPortalServer/SocialDataService\">" +   
  18.          " <url>" + url + "</url>" +   
  19.          "</CountCommentsOnUrl>" +   
  20.          "</soap:Body>" +   
  21.          "</soap:Envelope>"   
  22.          return soapXml;   
  23.      }   
  24.    
  25.      function processResult(content, txtFunc, xhr) {   
  26.          // Here we get the actual comment count   
  27.          //We can set this to any span element   
  28.          var commentsCount = $(content.responseText).find('CountCommentsOnUrlResult').text();   
  29.      }  
Finally from display template we can directly call ReturnCommentsCount(news url) and set the comment count to HTML element in front of news title like for example consider <span> element having id "commentcount" so like: 
  1. $("#commentcount”).text(commentsCount);  
Complete processResult method will be like: 
  1. function processResult(content, txtFunc, xhr) {   
  2.      // Here we get the actual comment count   
  3.      //We can set this to any span element   
  4.      var commentsCount = $(content.responseText).find('CountCommentsOnUrlResult').text();   
  5.      $("#commentcount”).text(commentsCount);   
  6.  }  

Issue with Custom DateTime Type Field on Page in SharePoint 2013

We faced a weird issue in our project. We have issue regarding Datetime field. We couldn’t find exact root cause but since it took lots of time to resolve so sharing.
 
We have SharePoint 2013 farm solution. We have custom DateTime type column is added in our custom content type and content type is associated with our custom page layout. This DateTime field is required field.
 
Content editor has created the page using our custom page layout but when he tried to save / publish the page, error dialog box with following error is appearing
 
 “The file Test.aspx has been modified by <User> on <Date>”
 
Even though not any other user has been modifying the page. On above error dialog when we pressing “OK” button and save it again following error is appearing
  

We investigated a lot but no luck. Only solution which we found is that making the DateTime field optional. We did this change and it started working without any problem