Wednesday, September 10, 2014

Static Member in C#

A good explanation and examples are found at http://csharp.net-tutorials.com/classes/static-members/

public class Rectangle
{
    private int width, height;
    public Rectangle(int width, int height)
    {
        this.width = width;
        this.height = height;
    }
    public void OutputArea()
    {
        Console.WriteLine("Area output: " + Rectangle.CalculateArea(this.width, this.height));
    }
    public static int CalculateArea(int width, int height)
    {
        return width * height;
    }
}


I like the author's example using Rectangle.CalculateArea( this.width, this.height) as an example of using a static member in a non-static class.

Thursday, September 4, 2014

Entity Framework : Update only changed fields instead of all fields

If we follow the Entity Framework's general approach to edit, it would be something similar to this.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "FacilityID, FacilityName, AddressLine1, AddressLine2")] 
Facility facility)
{
  ...
  if( ModelState.IsValid )
  {
    db.Entry(facility).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
  }
..
}

The code in the above treats all fields as `Modified` and saves all field data into the database whether the old and new value of each field is the same or different.

However, there are times that we need to update only certain fields, instead of updating all fields data. The above example would update all field data (FacilityName, AddressLine1, AddressLine2), even when only AddressLine1 was changed by user. In order to save only the changed field data into the database, we can try the following approach: compare each field's value between old and new first and perform update only on the ones that are different.
using System.Data.Entity.Infrastructure;
...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(
  [Bind(Include = "FacilityID, FacilityName, AddressLine1, AddressLine2")] 
   Facility facility)
{
  ...
  if( ModelState.IsValid)
  {
    db.Facilities.Attach( facility );
    DbEntityEntry entry = db.Entry( facility );
    foreach( var propertyName in entry.OriginalValues.PropertyNames )
    {
      // Get the old field value from the database.
      var original = entry.GetDatabaseValues().GetValue<object>(propertyName);
      // Get the current value from posted edit page.
      var current = entry.GetCurrentValues.GetValue<object>(propertyName);
      if(!object.Equals(original, current))
      {
        entry.Property( propertyName ).isModified = true;
      }
    }
    db.SaveChanges();
  }
}


Here we first get all property names (field names) and inspect each property's old and new values. Old values are retrieved from the database. New values are ones submitted by user through post.
// Get the old field value from the database.
var original = entry.GetDatabaseValues().GetValue<object>(propertyName); 
// Get the current value from posted edit page.
var current = entry.GetCurrentValues().GetValue<object>(propertyName); 
When the two values of original and current of a property are not equal,
that property will be assigned `IsModifed = true`, and its current value will be saved into the database.

On the other hand, if current field's values exist in the database already, those field values will be skipped while db.SaveChanges() is performed .


Remove containment from draggable jQuery UI Dialog

By default,  a draggable jQuery UI Dialog has containtment such that when you drag the dialog, you will be restricted by the browser's window. While comparing this default behavior against SharePoint's modal detail/edit dialog, SharePoint's dialog feels more user friendly and natural, because it lets users drag the dialog beyond the browser window. It simply feels natural to be able to move around the modal dialog outside browser window so that you can view the underlying main page's data as much as possible.

To remove containment from a draggable jQuery UI Dialog, try the following.
The trick is to use draggable's containtment property via widget of the dialog.

// Button that opens the dialog and a div to be used as the dialog
<input type="button" id="btnOpenDialog" value="Open Dialog" />
<div id="dialog"></div>
<script type="text/javascript">
  var myDialog = null; // global variable
  $(function(){
    $('#btnOpenDialog').on('click', function(){

      // Step 1.
      // Get the dialog ready.
      myDialog = $('#dialog').dialog({
        autoOpen: false, modal: true, resizable: true, width: 400, 
        buttons: {
          OK: function(){ // perform some actions ...},
          Cancel: function(){ $(this).dialog('close'); } // close the dialog 
        }
      });
      
      // Step 2.
      // `myDialog` is a global variable and has a reference to the dialog.
      // Use `myDialog` to remove containment from the dialog.
      myDialog.dialog("widget").draggable({ containment: false });

      // Step 3.
      // Show the dialog
      myDialog.dialog("open");

    });
  });
  
</script>

Thursday, August 28, 2014

Using Less in Visual Studio 2013 Web Project

Here is a cheat sheet on "what to do" to start using LESS on Visual Studio 2013 web project.

  1. Install "dotless" using Package Manager Console ("install-package dotless") or the Nuget Package Manager
  2. Open Web.config, locate the "dotless" section, and change it as the following.
    The main thing is to add
    <validation validateIntegratedModeConfiguration="false"/>
    
    to the <system.webServer> node.
    <dotless minifyCss="false" cache="true" web="false" />
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <handlers>
          <add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" preCondition="" />
        </handlers>
    </system.webServer>
    
  3. If the main less file is "my.less", which imports all other less files, add the following comment at the top of each less file except the "my.less".
    /// <reference path="my.less" />
    

Wednesday, August 20, 2014

Enable vertical split of the same CSHTML view file in Visual Studio 2013

In Visual Studio 2013, you can open the same C# file twice and view them vertically side-by-side by opening the C# file, selecting the menu [Window] --> [New Window] and then selecting [Window] --> [New Vertical Tab Group]. However, for *.cshtml MVC View files, this does not work. The [Window] --> [New Window] menu item is grayed out. To enable [Window] --> [New Window] menu item for *.cshtml file, you can try this registry hack.

  1. Close Visual Studio 2013 if currently open.
  2. Use RegEdit and go to
    [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\Languages\Language Services\HTMLX] .
  3. Find "Single Code Window Only" entry. 
  4. Change its value from 1 to 0.
  5. Start Visual Studio.
Now you should be able to open a *.cshtml file, select [New Window] from the [Window] menu to open another editor window of the same *.cshtml file, right-click on the the new editor window's tab and select [New Vertical Tab Group] to create side-by-side editor view of the same file. Changes you make on one editor window will instantly appear on the other editor window of the same file. 


onclick event handler - get reference to the clicked element

There are a couple of ways to get the reference to the clicked element, which has onclick event on itself.


Method 1
<input type="button" id="btn1" value="Remove" onclick="removeSelf(event)" />

<script type="text/javascript">
  function removeSelf(e){
    var target = (e.target) ? e.target : e.srcElement // IE uses srcElement
    target.style.display = 'none'; 
    target.parentNode.removeChild( target ); // to remove the element
    $(target).remove(); // to remove the element using jQuery
  }
</script>

In Method 1, event is used as parameter. An Event object is created automatically whenever an event is fired, i.e., via user action, key press, mouse movement, etc. To find the source where the event occurred, the property name is either target or srcElement (in IE).


Method 2
<input type="button" id="btn1" value="Remove" onclick="removeSelf(this)" />

<script type="text/javascript">
  function removeSelf(object){    
    object.style.display = 'none';
    target.parentNode.removeChild( target ); // to remove the element
    $(target).remove(); // to remove the element using jQuery
  }
</script>


Monday, July 7, 2014

MVC Ad-hoc DropDownList for PageSize

Example of Razor DropDown List for PageSize in an Index View using ViewBag.

Here is a controller
public class ProductController : Controller
{
  public ActionResult Index( int? page, int? pagesize )
  {
    ...
    int pageSize = pagesize ?? 5;
 
    List<SelectListItem> items = new List<SelectListItem>{
      new SelectListItem{ Text="5", Value="5" },
      new SelectListItem{ Text="10", Value="10" }
    }
    
    // items = List<SelectListItem>
    // "Value" = ValueText
    // "Text" = DisplayText
    // pagesize = SelectedListItem's Value from querystring
    ViewBag.PageSizeList = new SelectList( items, "Value", "Text", pagesize );
    
    ViewBag.CurrentPageSize = pageSize
  }
}
Here is the view
@using PagedList
@using PagedList.Mvc
@model IEnumerable

<form id="form1" action=@Url.Action("Index", "Product") method="get">
...
  @Html.DropDownList( "pagesize", (SelectList)ViewBag.PageSizeList )
  // We keep DropDown list's name separate from ViewBag element's name


  @foreach ( var item in Model ) {  }
  <table><tbody>
  <tr><td>...</td></tr>
  </tbody></table>

  @Html.PagedListPager( (IPagedList)Model, 
    page => Url.Action( "Index", new { page, pagesize = @ViewBag.CurrentPageSize })

</form>
<script type="text/javascript" src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js">
</script>
<script type="text/javascript">
  $(function(){
    // When onchange event occurs on <select id="pagesize">, 
    // simply submit the form, which will submit the new pagesize value as querystring.
    $('#pagesize').on('change', function(){
      $('#form1').submit();
    });
  });
</script>