Monday, May 16, 2011

LINQ Lessons

In our recent project, we came across many situations where we had to write queries on our objects in the UI tier. Few of them are give below.

I am taking here the movie class to explain different Linq queries.
public class Movie
{
     public int ID {get; set;}
     public string Title {get; set;}
  public string Director {get; set;}
     public int Genre {get; set;}
     public int RunTime {get; set;}
     public DateTime ReleaseDate {get; set;}
     public decimal Budget{get; set;}

}

public List GetMovies()
{
return new List {
new Movie{Title="Rocky", Director="Alex", Genre=1, RunTime=180, ReleaseDate ="01/01/1990"},
new Movie{Title="Return of the Devil", Director="Michael", Genre=2, RunTime=80, ReleaseDate ="01/01/1998"},
new Movie{Title="Warriors", Director="Phil", Genre=3, RunTime=120, ReleaseDate ="01/01/1991"},
new Movie{Title="Love", Director="Kevin", Genre=4, RunTime=120, ReleaseDate ="01/01/1992"},
new Movie{Title="Live Forever", Director="Leonardo", Genre=5, RunTime=120, ReleaseDate ="01/01/1997"},
new Movie{Title="War", Director="Adams", Genre=6, RunTime=130, ReleaseDate ="01/01/2001"},
new Movie{Title="Crimes of the City", Director="Ricky", Genre=6, RunTime=130, ReleaseDate ="01/01/1995"},
new Movie{Title="Street Fighters", Director="Andrew", Genre=6, RunTime=130, ReleaseDate ="01/01/1995"},
new Movie{Title="Violence", Director="David", Genre=6, RunTime=130, ReleaseDate ="01/01/1998"},
new Movie{Title="College Days", Director="Clarke", Genre=4, RunTime=140, ReleaseDate ="01/01/1997"},

};
}


Query: Get all movies from generic movies collection.
var movies = GetMovies();
var query = from m in movies select m;

Query : Return a new projection containing Title and Genre.
var movies = GetMovies();
var query = from m in movies select new {m.Title, m.Genre};
or
var query = from m in movies select new {MovieTitle = m.Title, MovieGenre = m.Genre};

Query: Return all movies order by Title
var movies = GetMovies();
var query = from m in movies order by m.Title descending select m

Query: Adding a filter to a Linq query.
var movies = GetMovies();
var query = from m in movies where m.Genre=5 select m;

Query: Data Grouping
var movies = GetMovies();
var query = from m in movies group by m.Genre into g
            select new {Genre = g.key, Count = g.Count} 
            

Query : Linq Operators
var movies = GetMovies();
movies.Max(m=>m.RunTime)
movies.Min(m=>m.RunTim)
movies.Average(m=>m.RunTime)

Query: Linq Joins
var moveis = GetMovies();
var genres = GetGenres();

var query = from m in movies Join g in genres On m.Genre Equals g.ID
            select new {Title = m.Title, Genre = g.Name}
Query: Left Join
All movies from movies object irrespecitive of having a genre or not.

var m = from m in movies join g in generes on m.Genre equals g.ID into MovGen
              from MovGenJ in MovGen.DefaultIfEmpty()
             select new {Title = m.Title, Genre = g.Name}

Query: Paging using Linq

var query = (from m in movies Join g in generes On m.Genre Equals g.ID 
             select new {Title = m.Title, Genre = g.Name}).Skip(10).Take(10);
Query: For loop in Linq

var m = movies.ForEach(m =>m.Budget = GetMoviesBudget(m.ID))

Tuesday, May 10, 2011

What's new in VS2010



Web.Config Transformation


As we all know that Web.config in Dev environment is never same in Test and Prod environment. We have to replace couple of entries like Connection string etc. for Test and Prod.

VS2010 gives an excellent feature called as Web.Config Transformation to automate these changes. Let's see here how it is done.

1. Open Configuration Manager from Build menu.
2. Create a new Config file using Configuration Manager -> New
3. Lets name it as MyTransform.
4. Right click on the Web.Config file and select Add Config Transform. VS2010 will
create web.MyTransform.config file. This is the file where we will make our Prod entries.
5. Open the Web.Config file and add following entries.





6. Add the production entries in the web.MyTransform.config file as follows





7. For testing purpose, let's create an Application under Default Web Site on our local box. Let's assume this as Prod Url.
8. Now publish your Web Application to your Prod Url by Right click on Project and choose Publish.
9. Open the Physical path of the Prod Url and check the Web.Config file. You will find the "ProdBox" for the "ServerName" key in the appSettings section.

Thursday, May 5, 2011

ASP.NET MVC 3 Tools Update



This tools update will include following tooling improvement.

  1. Final release of EF 4.1.
  2. Built-in data scaffolding support
  3. New HTML5 project templates
  4. Intranet Project Template
  5. Newer versions of jQuery core, jQuery UI and jQuery Validation

Download

Tuesday, May 3, 2011

Breaking changes of Jquery 1.6



Case-mapping of data- attributes

In Jquery 1.5.2, an attribute of data-max-value="15" would create a data object of { max-value: 15 } but as of jQuery 1.6 it sets { maxValue: 15 }. It is done to match W3C HTML5 spec.

Handling of DOM properties and DOM attributes separatly
.prop() -
.removeProp() -
.attr() -

Properties represent the dynamic state of DOM, whereas Attributes represent the state of DOM information as retrieved from the document.
Ex: $(this).prop("checked") - returns current state of the checkbox.

Ajax
Bugs Fixed:

#6481: revert $.param should treat empty arrays/objects like empty strings
#7881: Make compatible with XHR 2
#8417: When posting AJAX and the data has “??” is formats it to jQuery?
#8744: .ajax() jsonp requests are not handled correctly when hitting timeout
#8884: jqXHR breaks names of custom header fields

Performance Improvement
.attr("alue");
.attr("name", "value")
.val() - get
.data()

boolean attributes

$(#checkbox).attr("checked","true"); - check it
$(#checkbox).attr("checked","false"); - Uncheck it

Bugs fixed
Bugs Fixed:

#1591: IE "Invalid Argument" $('table').attr('non-existent')
#3116: .attr does not work with SVG IDLs
#3786: removeAttr should use jQuery.props
#4283: .attr('checked') & XHTML 1.1 Strict
#4464: IE cannot get width attribute of detached IMG element
#4978: jQuery.prop missing cellpadding?
#5413: tag "img" width/height attribute is zero (IE)
#6562: using .attr() to set the ‘target’ attribute, with a node that has ID of 'target'
#6708: Opera has inconsistent result for usemap attribute value
#6823: Make .val(value) faster for common use case
#7472: $('form').attr('id') return DOM Element
#7485: Inconsistency between has [attribute] selector and attr() method
#7709: Permission denied to access property ‘nodeType’ from a non-chrome Firefox/3.5.15
#7996: Safari $('script').attr(‘event’); Bug
#8117: .removeAttr don’t works with select element’s size attribute
#8150: removeAttr issue in webkit, firefox
#8255: support for list attribute
#8418: set name parameter using attr() method in IE 7
#8457: attrHooks
#8570: .val method returning “on” for dynamically created radio buttons in ie9
#8699: .attr() returns -1 on missing attribute instead of undefined
#8772: Using .attr() to set input type 'range' causes script error in IE9
#8997: new attribute “form” (HTML5) is not supported, .attr(‘form’) not working properly
#9037: $('blah').attr('onclick') return event in Firefox

Event - Bugs fixed
#5884: live mouseenter/mouseleave events don’t fire as expected when nested
#6514: Mouseenter and mouseleave events not able to be triggered if bound by live
#6913: namespaced event bubbleing wrong
#6993: .bind() and .one() don’t allow a function as data
#7071: Accessing the ‘type’ property on VML elements fails on IE
#7883: .delegate (and .live) should accept false as the fn arg, like .bind
#8018: Unsafe access to frameElement causes error in crossdomain (i)frames
#8272: Exceptions in plain JS object event handlers swallowed by jQuery
#8712: Custom events don’t bubble up to window
#8732: Incorrect feature detect for IE9 focusin/focusout
#8753: jQuery 1.6: jQuery.Event contstructor to support setting properties
#8755: binding to beforeunload throws an error in IE6, 7, 8 on page unload
#8777: jQuery 1.6: undelegate() accepts custom namespaced events
#8788: Reorganize jQuery.event.trigger to use loop instead of recursion
#8790: Optimize non-attached events such as data events
#8803: jQuery.holdReady() method


Manipulation - Bugs fixed

#1954: val() returns innerHTML for button elements in IE
#6180: jQuery.clean should not touch script tags that are not of type text/javascript
#7623: Exception thrown in replaceWith
#7885: jQuery .offset doesn’t property works when current offset is float (which is possible in FireFox)
#8060: Setting checked to true on a disconnected checkbox does not carry over after attaching to DOM.
#8500: radios and checkboxes revert to default (HTML) state when wrapped in IE

Misc
Bugs Fixed:


#8203: Remove un-needed “someVar = null;”s
#8851: Wraps strings with double quotes in sources and tests
#8882: Tests: Update QUnit usage, replace id=main with id=qunit-fixture


Selector
:focus Selector

In jQuery 1.6 we now ensure that the :focus selector works properly across all browsers. You can use this selector to find the currently focused element on the page (such as a form input).

$("input:focus").addClass("active");

#3685: Selector fails for forms with an element named “name”
#4321: $(“#”) returns undefined
#8105: :focus selector filter


Support
Bugs Fixed:


#9028: IE8 crashes while loading 1.6rc1 if using body background image


Traversing

find(), closest(), and is() now all take DOM elements and jQuery objects
In jQuery 1.6 we’ve ensured that find(), closest(), and is() can all take DOM elements and jQuery objects as arguments. This gives you alternatives for filtering sets of elements based upon the passed-in elements.

// Only returns .test elements if they're inside of a div
$("div").find( $(".test") )

Bugs Fixed:

#2773: $.fn.is and $.fn.not should accept DOMelements and jQuery collections
#5712: Allow jQuery.fn.is to accept a function
#6912: $().add(selectElement) adds option children instead
#7369:
$('
ff
').closest('[attr]');
raises exception in all browsers
#8609: Result of .find("") is undefined

Reference : http://blog.jquery.com/2011/05/03/jquery-16-released/

Thursday, April 28, 2011

Impact of Content Type changes on existing Lists in SharePoint 2007

In real world, we come across of many business scenarios that force us to add/edit/remove some columns to our existing Lists. Sometimes these Lists are heavily populated with large amount of data and workflows running on them. As we all know we add columns to a SharePoint List using Content Types for reusability purpose. So changing the columns of a List means changing the Content Type associated with the List. In such a situation, several questions come to one's mind.

1. Can I simply add the new field references to my existing ContentType CAML and re-activate the feature ? Will the new fields be added to the existing Lists ? Will it impact the running workflows on the Lists ?

We all know for sure that the new fields will be part of a new List that we create after the change. But what about the existing Lists. Simply adding the new field references to the existing Content Type CAML will not reflect in the existing Lists. You need to add these field references programmatically inside a feature receiver by passing true to the Update() method of the Content Type. Here is the sample code snippet.


public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb web = ((SPSite)properties.Feature.Parent).OpenWeb())
{
SPContentType pcType = web.ContentTypes[new SPContentTypeId("GUID of the existing Content Type")];
SPField newField = web.Fields[new Guid("GUID of Field")];
SPFieldLink newFieldLink = new SPFieldLink(newField);
pcType.FieldLinks.Add(newFieldLink);
pcType.Update(true);
}
}


Any change in the Content Type should not impact the running workflows on the Lists.

When we remove fields from an existing Content Type and re-deploy it, the same columns would not be removed from the Lists that use the Content Type. Safety of the List Data is utmost important for SharePoint.

At the end, Don't forget to remove these field references inside feature deactivating event.

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
using (SPWeb web = ((SPSite)properties.Feature.Parent).OpenWeb())
{
SPContentType pcType = web.ContentTypes[new SPContentTypeId("GUID of the existing Content Type")];
SPField newField = web.Fields[new Guid("GUID of Field")];
if (pcType.Fields.ContainsField(newField .Title))
pcType.FieldLinks.Delete(new Guid(GUID of Field));
pcType.Update(true);
}
}


Some facts related to Content Type -
If you delete the content type associated to a List, then it won't delete the columns in the List. They would be still exist as local columns. if you want to remove them from your List, then you have to delete them manually or programmatically.

What's New in C# 4.0

1) Optional Parameters


public class Order
{
//Old way
public int Purchase(Product product, Customer customer, bool isResale, string discountCode)
{

}
// New way
public int Purchase(Product product, Customer customer, bool isResale = false, string discountCode = string.Empty)
{
}
}
public class Program
{
static void Main(string[] args)
{
Order newOrder = new Order();
Product item = new Product { ItemCode = "A8901", Price = 50, Qty = 5};
Customer customer = new Customer();
customer.UserName = "R887663";
customer.PreferredCustomer = true;
newOrder.Purchase(item, customer);
}
}


2. Named Parameters


public class Program
{
static void Main(string[] args)
{
Order newOrder = new Order();
Product item = new Product { ItemCode = "A8901", Price = 50, Qty = 5};
Customer customer = new Customer();
customer.UserName = "R887663";
customer.PreferredCustomer = true;
newOrder.Purchase(item, customer, discountCode: 76883987);
}
}

3. Use of dynamic keyword


static class DynamicDemo
{
public static void Execute()
{
var person = new Person { Name = "Alex" };
var company = new Company { Name = "Microsoft" };

DoSomething(person);
DoSomething(company);
}

static void DoSomething(dynamic item)
{
Console.WriteLine(item.Name);
}
}

class Person
{
public string Name { get; set; }
}

class Company
{
public string Name { get; set; }
}



4. Use of DynamicObject


class DynamicObjectSimpleDemo : DynamicObject
{
private Dictionary members = new Dictionary();

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return this.members.TryGetValue(binder.Name, out result);
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.members[binder.Name] = value;
return true;
}
}

public class DynamicObjectXDemo : DynamicObject
{
private XElement element;

public DynamicObjectXDemo (XElement element)
{
this.element = element;
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this.element.Attribute(binder.Name).Value;
return true;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.element.SetAttributeValue(binder.Name, value);
return true;
}
}

class program
{
static void main(string[] args)
{
dynamic sample = new DynamicObjectSimpleDemo();
sample.Fname = "Alex";
sample.LName = "Palle";

var xml = XElement.Load("Clients.xml").Elements().Select(x => new DynamicObjectXDemo(x));

foreach (dynamic item in xml)
{
Console.WriteLine(item.FName+ " " + item.LName);
}
}
}

//Clients.xml









What's New in ASP.NET 4.0

1. In .NET Framework 4.0, the major configuration elements are moved to machine.config and applications now inherits these settings.
Sample of ASP.NET 4 Web.Config file









2. Output caching in ASP.NET 4 enables you to configure one or more custom output- cache providers. Output-cache providers can use any storage mechanism i.e. local or remote disks, cloud, distributed cache engine etc. to persist HTML content.
Example of specifying a different output-cahce provider for web page or web user control.


<%@ OutputCache Duration="60" VaryByParam="None"
providerName="DiskCache" %>


3. Some ASP.NET applications need to load large amount of data during initilization of the application before serving the first request. Prior to Asp.NET 4.0, we achieve the compilation of the application before the first request using the command Aspnet_compiler -v /MyWebSite. In Asp.NET 4.0, auto-start feature is available when ASP.NET 4 runs on IIS 7.5 on Windows Server 2008 R2.

You need to set following configuration in the ApplicationHost.config file.







If your application pool containing multiple applications, you can auto-start individual applications by setting the following configuration in applicationHost.config file.






The auto-start feature enables you to

  1. Start up the Application pool.
  2. Initialization of the Application
  3. It temporarily stops processing any http request till the initilization process is over.


4. The ASP.NET Redirect method results an extra round trip while doing a temporary redirect to an URL. ASP.NET 4.0 adds a new Helper method RedirectPermanent() that saves an unnecessary round trip.
While the Redirect method returns HTTP 302(Found) response, the RedirectPermanent() method issues HTTP 301(Permanent) response.

5. In Asp.net, The out of process Session State involves serialized session date sent to remote storage. It becomes a performance bottleneck if the data involved is large. The ASP.NET 4.0 Session State Compression feature helps to reduce the size of the data by compressing the Session State using GZipStream class. The Applications that have spare CPU cycles on the Web Server can achieve substantial performance improvement by using this feature.

You can set this option using the new compressionEnabled attribute of the sessionState element in the configuration file.

6. ASP.NET 4.0 allows you to configure the application URL path, query string length and invalid characters that are not allowed in the application url. You can configure them as follows.





7. The ASP.NET 4.0 System.Runtime.Caching API provides an uniform caching technique for all .NET applications (Web, Windows Form). It provides abstract types for custom cache implementation and a concrete in-memory object cache class called MemoryCache.

8. In ASP.NET 4, you can create custom encoding routines for the following common text-encoding tasks:

  • HTML encoding.
  • URL encoding.
  • HTML attribute encoding.
  • Encoding outbound HTTP headers.


Configure the custom encoding routines as follows:




9. CDN base Ajax and Jquery loading to ASP.NET 4.0 Applications.






[assembly: WebResource("Example.js", "application/x-javascript", CdnPath ="http://contoso.com/app/site/Example.js")]



10. 2 new properties are added to the Page class i.e. MetaKeywords, MetaDescription that helps set meta tags for search engine submission. The html rendered on the browser by these 2 properties is as follows:


<html>
<head>
<meta name="keywords" content="keyword1, keyword2"/>
<meta name="description" content="description"/>
</head>
<html>


11. A New property ViewStateMode is added to Control class. Setting ViewStateMode=false of the Control class disables viewstate for all the controls on the page. You can use ViewStateMode property of indiviual control to enable view state explicitly.

12. ASP.NET MVC way of routing in ASP.NET 4 Web Forms.

13. We use a Control's Client ID property to access that control in client script. Prior to ASP.NET 4.0, the Client ID is generated automatically by ASP.NET engine and sometimes it is difficult to predict the Client ID of a control to use in client script. In ASP.NET 4.0, you can specify how it can be generated by using ClientIDMode property at Page level or control level. It has following values:

Auto - It provides the same behaviour ASP.NET was providing prior to ASP.NET 4.0

Static - Instead of automatically generating Client ID, it sets the ID of the control as Client ID.

Predictable - For a Data Bound control, You can control how the ID of each instance of the control would be created by using ClientIDRowSuffix property. The value of this property will be appended to the Client ID property of each instance of the control.

Inherit - Inherit the ClientIDMode property of the container control to generate the Client ID of the control. If the control doesn't have a container control then it uses the ClientIDMode property of the Page.

The default mode for a site or page is - Predictable
The default mode for a control is - inherits

The following example shows how to set the default ClientIDMode for a site in the Web.config file.





The following example shows how to set the default ClientIDMode for a page in the @ Page directive.


<%@ Page Language="C#" CodeFile="Default.aspx.cs"

Inherits="_Default" ClientIDMode="Static" %>


14. Persisting row selection in Data Controls - Rows selected in Pages will be persisted across pages. When you select a row 3 on Page1 and move to Page8. If you go back to Page1, you will see row3 as selected. To achieve this, use PersistedSelection property of the Data Control.






15. Filtering date with the QueryExtender control. The Query Extender control can be added to EntityDataSource or LinqDataSource to filter the data. The QueryExtender has following filter options-


ContextTypeName="AdventureWorksDataContext" EntityTypeName=""
TableName="Products" >



SearchExpression -
RangeExpression-
PropertyExpression-
OrberByExpression-
CustomExpression-


<html>
<head runat="server">
<title>Filter Demo</title>
</head>
<body>
<form id="form1" runat="server">
Search:<asp:TextBox ID="SearchTextBox" runat="server" />
<p>

Make More:<asp:CheckBox ID="MakeCheckBox" runat="server" />
<p>
From:<asp:TextBox ID="FromTextBox" runat="server" ></asp:TextBox>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
To:<asp:TextBox ID="ToTextBox" runat="server" ></asp:TextBox>
</p>
<p>
<asp:Button ID="Button1" runat="server" Text="Search" />
</p>
<asp:LinqDataSource ID="LinqDataSource1"
ContextTypeName="FilterDemo.AdventureWorksDataContext"
TableName="Products" runat="server">
</asp:LinqDataSource>
<asp:QueryExtender runat="server" TargetControlID="LinqDataSource1">

<asp:SearchExpression SearchType="StartsWith" DataFields="Name" >
<asp:ControlParameter ControlID="SearchTextBox" />
</asp:SearchExpression>

<asp:RangeExpression DataField="ReorderPoint" MinType="Inclusive" MaxType="Inclusive">
<asp:ControlParameter ControlID="FromTextBox" />
<asp:ControlParameter ControlID="ToTextBox" />
</asp:RangeExpression>

<asp:PropertyExpression>
<asp:ControlParameter ControlID="MakeCheckBox" Name="MakeFlag" />
</asp:PropertyExpression>
</asp:QueryExtender>

<asp:GridView ID="GridView1" runat="server"
DataSourceID="LinqDataSource1" AllowPaging="True"
DataKeyNames="ProductID>
</asp:GridView>
</form>

</body>
</head>
</html>