Tuesday, February 22, 2011

ProjectLinker extension for Visual Studio

Recently we were developing an application in silverlight which will consume WCF for doing some business operations and data access. WCF was designed using MessageContracts and DataContracts concept. Each operation will translate to input and output DataContracts. This WCF is not an tranditional one in which when you add reference you will get all the data contracts. So we will have to share all these DataContracts to Silverlight app. There arised the problem, since the Desktop/Web class library project cannot shared in silverlight app. So we thought of creating a separate silverlight class library replicating all the classes. This will be a serious maintenance nightmare!!!!
That time, I came across the concept of ProjectLinker synchronization tool. This is specially designed to address such scenarios. Basically Multi-targeting framework.
Bingo!!! Problem solved. Using this we can share the same class files between different platforms nothing but between the Desktop/Web class library and Silverlight class library.

You can find more about how to use this tool in the below link;
http://msdn.microsoft.com/en-us/library/ff921108(v=pandp.20).aspx

Download Project Linker for VS2008 here;
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=387c7a59-b217-4318-ad1b-cbc2ea453f40&displaylang=en

Download Project Linker for VS2010 here;
http://visualstudiogallery.msdn.microsoft.com/5e730577-d11c-4f2e-8e2b-cbb87f76c044/

Thursday, January 6, 2011

Issues With Programmatically Attaching Multiple Files To A List Item

Recently one of my team member was facing issue while adding multiple files to a list item programmatically. The issue was, about 10% files added programmatically were corrupt while uploading. So whenever the user tries to download the file, they were getting "HTTP 500 Internal Server". Below is the piece of code he was using;

HttpFileCollection uploads = HttpContext.Current.Request.Files;


for (int i = 0; i < uploads.Count; i++)

{


HttpPostedFile upload = uploads[i];


if (upload.ContentLength == 0)


continue;


Stream inputStream = upload.InputStream;


byte[] buffer = new byte[inputStream.Length];


inputStream.Read(buffer, 0, (int)inputStream.Length);


inputStream.Close();


eItem.Attachments.Add(upload.FileName, buffer);


}


eItem.Update();
 
On analysing we found out that, the issue was with Attachments.Add method. It was causing some corruptions in the bytes uploaded. So we tried with Attachments.AddNow..
Bingo!!! It started to work without any issues.
 
The only difference between "Attachments.Add" and "Attachments.AddNow" was, "Attachments.AddNow"; it will create new version whenever you attach.
Also, "Attachments.AddNow" internally calls the "Update" method of the List Item. Though its very weird, it is solving the problem of bytes corruption while uploading multiple attachments to the list item.

Friday, December 31, 2010

Search a text in all properties of an object in collection (FullTextSearch) using LINQ

Recently in our project, we had a requirement to search for particular character in the List. The search is similar to FullTextSearch which means, we need to search for a specific character in each and every property of an object contained in the list..
We initial thought the only way is to use LINQ to add condition for every property with OR statement. Then while googling got one idea from this link;
http://manfred-ramoser.blogspot.com/2009/09/full-text-search-for-entity-framework.html

This exactly does the same what we needed except failed in one scenario. (i.e.) this failed when any of the property is NULL. So I modified the code a little bit which take cares of the NULL situation as well. Below is that code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;


namespace TestXML
{
public static class QuerableExtensionMethods
{
public static IQueryable<T> FullTextSearch<T>(this IQueryable<T> querytable, string searchkey)
{
return FullTextSearch<T>(querytable.AsQueryable<T>(), searchkey, false);
}


public static IQueryable<T> FullTextSearch<T>(this IQueryable<T> querytable, string searchkey,bool exactMatch)
{


ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
ParameterExpression stringParameter = Expression.Parameter(typeof(string), "d");
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
MethodInfo nullMethod = typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) });
var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Where(p => p.PropertyType == typeof(string));
Expression orExpression = null;


string[] searchKeyParts = null;


if (exactMatch)
searchKeyParts = new[] { searchkey };
else
searchKeyParts = searchkey.Split(' ');


foreach (var property in publicProperties)
{
Expression nameProperty = Expression.Property(parameter, property);
foreach (var searchKeyPart in searchKeyParts)
{


Expression searchkeyExpression = Expression.Constant(searchKeyPart);
Expression nullCheckExpression = Expression.Constant(null);
Expression callContainsMethod = Expression.Call(nameProperty, containsMethod, searchkeyExpression);
Expression nullCheckMethod = Expression.Call(stringParameter, nullMethod, nameProperty);
Expression notExpression = Expression.Not(nullCheckMethod);


if (orExpression == null)
orExpression = Expression.AndAlso(notExpression, callContainsMethod);
else
orExpression = Expression.Or(orExpression, Expression.AndAlso(notExpression, callContainsMethod));
}
}
MethodCallExpression whereCallExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { querytable.ElementType }, querytable.Expression,
Expression.Lambda<Func<T, bool>>(orExpression, new ParameterExpression[] { parameter }));


return querytable.Provider.CreateQuery<T>(whereCallExpression);
}


}
}

Happy coding and wishing all the viewers of my blog happy and prosperous new year!!!!

Wednesday, December 15, 2010

Counter-Queue and Counter-Wait Pool Patterns for SaaS Implementations

SaaS or Software as a Service is the upcoming paradigm shift in the IT industry. Everyone is shifting towards converting their offerings to Cloud platforms. Some of the key things in this model are the; 
  • Effective utilization of the resources available
  • Satisfy as much service requests as possible with the available resources
  • High Throughput

 The Counter-Queue Pattern is an attempt to increase the productivity of the SaaS offerings using the real life scenario of Ticket booking counters in the Railways Stations. Like in the booking counters, the service requests will be piled up in the queues available and executed in parallel. Say we plan to have 10 queues; the service requests available in the 10 queues will be executed in parallel. The diagram below pictorially explains the Counter-Queue pattern;

  1. Initially, the service requests will be put in the “Input Queue”
  2. The queue manager reads the service requests in the “Input Queue” and allocates them to the “Counter Queues” available. Each counter queue will have the max queue size, depending on that, the queue manager allocates the service requests in them
  3. Each counter will perform the similar functionality. They will pick up the service requests in their respective counter queues and perform the necessary functionality and put the result in the “Output Queue”

In case, any counter fails; the service requests will be moved back to the end of the “Input Queue” for re-allotment. As you can notice, the problem here is that when any counter fails; SLA of the service requests in those queues will not be met.

The “Counter-Wait Pool pattern” will solve this problem. The below diagram pictorially explains this pattern


  1. Initially, the service requests will be piled up in the input queue
  2. The queue manager picks the service requests from the “Input Queue” and assigns a sequential number to it and put in the wait pool. There will be a max size set to the wait pool. Depending on that, queue manager will put the service requests in the wait pool.
  3. Each counter will have “Next token” display in them. Depending on the number displayed, the service requests will be picked from the wait pool.
  4. Once the counter services the request, the result will be put in the “Output Queue”.

As you can notice, here we will not run into the problem of not meeting the SLA of the service requests on any scenario 

Monday, December 13, 2010

Forbidden 403 error while accessing workitems in TFS2010 sharepoint site Dashboard

Sometimes you may experience the "Forbidden 403" error in TFS2010 when you try to access the workitems from Dashboard in Sharepoint site.

Here is the solution for that;
1) Login to the TFS Application server
2) Locate the directory "C:\inetpub\wwwroot\bin"
3) Give Write permission for the users of TFS

Bingo, now you should be able to access workitems from Dashboard.