« September 2006 | Main | November 2006 »
Some time back while working on a project we had requirement to do input data cleansing. The input would be a known XML format and could come from know sources. However each source could have used a different string representation than a standard one and hence it was required to fix this prior to working with the XML. For example we would want the color to be represented as "green", while the input could contain GREEN, GRN, grn etc.
There were some common conversions which were to be done for any source. However some conversions were only to be done for specific sources and additionally support was required to add new sources at any time without rebuilding the application. We discussed and decided that Mapping won't work since, one we needed a generic string replacement as against specific XML node manipulation and two we wanted dynamic addition of sources.
What follows is a discussion of the solution that we implemented. I would like to acknowledge the support from my colleague Jitendra Pal Thethi in coming up with this solution and the code base. Considering the different string manipulations required for each source and ability to dynamically add new sources, we decided to use Business Rules Engine (BRE) along with a custom .net component that do the actual execution. Following are some sample rules that we built for this functionality. The first one was to handle the generic case i.e. the rule that will run for all sources.
IF
Conditions
SourceName is not equal to ""
THEN
Actions
Replace GRN with green
Replace string1 with string2
Replace string3 with string4
For a specific source, the Conditions part was altered to as below, while the actions were written in similar manner. Only the values of the strings to replace were altered as required.
IF
Conditions
SourceName is equal to SourceA
At any given time a new rule could be added for a new source as required and when deployed, the new policy will be picked up and be used and thus allowly easy dynamic addition of new source handling.
The final rule to trigger the actual string replacement was something like this
IF
Conditions
1 is equal to 1
THEN
Perform ReplaceAll
The condition of 1 equal to 1 forced the rule to be always executed. This can be optimized by looking up the count of strings identified for replacing. If the count is 0, we can skip executing any further code. However since BRE loads all facts and checks them upfront to build the agenda, if we did something like StringCollection.Count, it would return 0 always since at the start of execution there aren't any strings yet added. This means that even if we later add strings to the collection, the rule will still not fire since it never got added to the agenda. This can be easily addressed by doing an Assert to tell BRE that a fact has been updated. However this is also easily implemented as part of our custom .net component so we left the rule simple.
As I mentioned earlier, we also had written a custom .net component to do the actual execution. The SourceName, Replace and ReplaceAll as used in rules above are vocabularies built over this class. To capture the string values that represent the source and destination, we created a custom class as below
[Serializable]
public class ReplaceInfo
{
private string sourceString;
public string Source
{
get { return sourceString; }
set { sourceString = value; }
}
private string destString;
public string Target
{
get { return destString; }
set { destString = value; }
}
}
This class was then used in our Entity class that had a List collection to store the ReplaceInfo type. Part of this Entity class is shown below. Other than this it also had a private XmlDocument member that represented the input XML message.
[Serializable]
public class Entity
{
private XmlDocument doc;
public XmlDocument MessageData
{
get { return doc; }
set { doc = value; }
}
private string providerField;
public string SourceProvider
{
get { return providerField; }
set { providerField = value; }
}
private List<ReplaceInfo> listField = new List<ReplaceInfo>();
public List<ReplaceInfo> ReplaceStringCollection
{
get { return listField; }
}
...
...
...
}
The SourceProvider property of the Entity class, as shown above, returned the name of the current Source and it was on the get accessor of this the SourceName vocabulary was built. We then need a class to execute the strings stored in the Entity class and also add strings to be replaced to the list collection in the class. This was done using another class as below
[Serializable]
public class RuleExecutor
{
public void AddString(string strFrom, string strTo)
{
ReplaceInfo r = new ReplaceInfo();
r.Source = strFrom;
r.Target = strTo;
entity.ReplaceStringCollection.Add(r);
}
public void ReplaceAll()
{
StringBuilder sb = new StringBuilder(entity.MessageData.InnerXml);
foreach (ReplaceInfo rInfo in entity.ReplaceStringCollection)
{
sb.Replace(rInfo.Source, rInfo.Target);
}
//done with the string replacements.. put the modified XML back in the
//property variable from where the orchestration will pick it up
entity.MessageData.InnerXml = sb.ToString();
}
...
...
...
}
The AddString method of this class is set as the Replace vocabular that is used as part of the Actions of the rules mentioned earlier and the ReplaceAll method is set as the ReplaceAll vocabulary. Since BRE offers setting a more user friendly display name, we set the "AddString" .net class method as "Replace {0} with {1}", as seen in the rule snipper earlier.
This way we built an easy mechanism to manipulate strings and also had the ability to add more sources at run time. To test the rules we also built fact creator by implementing the IFactCreator interface and providing implementations for CreateFacts and GetFactTypes methods.
It's been a while since I did Blogging here as I was stuck in couple of other issues. This time thought of speaking about this topic (Restrict Access to Valid Users group across Team Projects). Though it is a very low level feature, I felt that lot of people will agree with me when I say "Valid Users group should not have access to all the data of projects on a TFS Server (though in read only mode) as it can contain sensitive/confidential data". Here we will see how to restrict this access by removing the read only permission to Valid Users Group during the project creation time.
We all know that when working with Winform applications and threads, we need to be careful about accessing the UI controls. These controls are meant to be accessed only on the thread that built them, which in this case is the primary application thread.
In multithreaded applications, when additional threads are used to perform background jobs to ensure that the UI remains responsive, one has to be careful about updating the controls on the form. There are articles already, that talk about how to address this problem. Check here.
With .net framework 2.0 and VS2005, there are improvements that help work with this issue easily. One of the improvements is the more user friendly exception display that occurs when running the application in debug mode. If your code does cross thread access, it will result in a error message like the following

.Net 2.0 also introduced a new class called BackgroundWorker class. This class has support for doing a lengthy work in background and then posting the completion event to the primary thread. This way in the completion event handler, you can safely update the UI controls without worry of cross thread access.
The article that I refered to earlier, talks about possibilities of using Invoke or BeginInvoke, where we know that the BeginInvoke method does the same work, but asynchronously. One can additionally call this.InvokeRequired to check if we really need to make the Invoke call or the execution is already on the primary thread. With my background in having done lot of Windows programming and working with DispatchMessage and TranslateMessage APIs and also writing message handlers in WndProc, I knew that when BeginInvoke or Invoke is called, it is bound to be doing a PostMessage to the primary thread, but I wanted to really how this was being done.
Needless to say that Lutz Reoder's .Net Reflector came in handy. Without going into line by line details of the internal workings, I will capture the key points here and you are welcome to drill down deeper into this on your own.
The Invoke/BeginInvoke methods support two overloads. One, that takes only a delegate (for callback and actual execution of UI updation logic) and another that takes the delegate as well an object array that you may want to pass to the delegate. The definition of the delegate is really upto the programmer based on the logic required to update the UI controls. The single parameter overloads call the second overload internally by passing null for the second parameter. For example
public IAsyncResult BeginInvoke(Delegate method)
{
return this.BeginInvoke(method, null);
}
These methods then internally use the MultithreadSafeCallScope internal private class to ensure that the further execution happens in a thread safe way. Eventually the call is made to the control's MarshaledInvoke private method. The method signature is
private object MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous)
The Delegate and the object array parameters are the ones that have been sent from the calling code. The synchronous boolean is set based on if the call is make from Invoke (true) or BeginInvoke (false). The key to this message execution is the check on the current executing thread ID and the thread ID of the control's creation thread. The calls are made using another internal class called SafeNativeMethods. The method calls of interest here are
1. SafeNativeMethods.GetCurrentThreadID : This is a method found in kernel32.dll and as the name suggests, gets the ID of the thread on which the code is currently executing.
2. SafeNativeMethods.GetWindowThreadProcessID : This is a method found in User32.dll and is used to find the thread that created the Window (the Winform in current context) and optionally the process ID also.
You can check Windows SDK documentation for more details on these methods.
The comparison of the thread IDs returned by these methods essentially decides the fate of further execution. If the two values are equal, this means that the current call is already happening on a thread that created the UI and hence can be used to safely modify the UI controls, else, it means that this is a different thread.
A new ThreadMethodEntry is created with the parameters passed to the Invoke/BeginInvoke methods and also capturing the current execution context. This entry is added to the ThreadCallbackList. If we are already on the right thread, a call is made to executed the delegate that the calling code had passed, else, a call to UnSafeNativeMethods.PostMessage is done to post the message to the thread's queue. People with windows programming experience will know the significance of PostMessage or SendMessage Windows APIs.
Finally, if the call came in via Invoke method, i.e. the synchronous parameter is true, the code waits for completion of execution using WaitForWaitHandle, else if called via BeginInvoke, the call completes and the IAsynchResult is returned to the calling code. Since the intention is to update the UI controls via the methods registered using the delegate, most likely you aren't bothered about the IAsynchResult result and in time the call to the delegate will complete, when the primary threads gets around to process its message queue.
To conclude, following are two ways to use the Invoke/BeginInvoke methods. In the code below, I have shown using BeginInvoke, but the same can be replaced with Invoke to get synchronous execution.
Option 1 : Using this.InvokeRequired. This is done when the same method updates the UI controls so need to ensure if we are on the right thread.
private void btnProcess_Click(object sender, EventArgs e)
{
//queue the work for thread processing
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
}
private void ThreadProc(object stateInfo)
{
//do some thread specific work here..
//simulate long work by sleeping for 2 secs
Thread.Sleep(2000);
//done. Update UI
SetTextOnControls()
}
private delegate void UICallerDelegate();
private void SetTextOnControls()
{
if (this.InvokeRequired)
{
UICallerDelegate dlg = new UICallerDelegate(SetTextOnControls);
BeginInvoke(dlg, null);
}
else
{
label1.Text = DateTime.Now.ToShortTimeString();
label2.Text = DateTime.Now.ToShortTimeString();
button1.Text = DateTime.Now.ToShortTimeString();
textBox1.Text = DateTime.Now.ToShortTimeString();
}
}
Option 2 : Without using this.InvokeRequired.
private void btnProcess_Click(object sender, EventArgs e)
{
//queue the work for thread processing
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
}
private void ThreadProc(object stateInfo)
{
//do some thread specific work here..
//simulate long work by sleeping for 2 secs
Thread.Sleep(2000);
//done. Update UI
UICallerDelegate dlg = new UICallerDelegate(SetTextOnControls);
BeginInvoke(dlg, null);
}
private delegate void UICallerDelegate();
private void SetTextOnControls()
{
label1.Text = DateTime.Now.ToShortTimeString();
label2.Text = DateTime.Now.ToShortTimeString();
button1.Text = DateTime.Now.ToShortTimeString();
textBox1.Text = DateTime.Now.ToShortTimeString();
}
Hi,
While I have been handling the Legacy Modernization (LM) solution, my colleague Ananthalakshmi's (Lakshmi) focus has been SOA realization on the MS platform.
An increasing number of customers are interested not just in piecemeal LM techniques but on a roadmap that will help move their enterprise architecture to SOA. In fact, a survey carried out by Infosys for its customers indicated that 66% of the respondents were interested in modernization strategies for service enabling their legacy systems.
Click the following link to find out how you can register and attend a webinar on Service Enabling Mainframes that is being jointly presented by Lakshmi and me http://www.infosys.com/events/service-enabling-mainframes-webinar.asp
Karthik
In my previous blog, “Enhanced Client Side Functionalities in ASP.NET 2.0,,,”, I had mentioned that the sample code can be further simplified with Atlas, because ASP.NET 2.0 AJAX Extensions provide a control to invoke Web Service from client side. Atul had rightly commented that this facility is not so quite new as I had sounded it in my blog. I am totally agreeing to his comments that Atlas may be a new bottle to old wine – XMLHttp and AJAX. But, for me, new bottle is so attractive and handy that I feel the same old wine tastes much betterJ. Yes, Atlas is conceptually the wrapper over many things (“behavior” is definitely one of them) that have been here for quite some time. But, I think that AJAX in its new avatar, now, is more powerful, flexible and much more integrated to visual studio. It does not force us to write tons of script, as it does most of the grunt work, in background quietly. That is why it would excite the development community.
Atlas provides flexibility to the coding, by supporting two approaches, one in which, we can write minimal javascript and DHTML here and there or we can go ahead with pure declarative programming model provided by it.
But, to see its flexibility, let me just take the example of consuming the web service from the client side. In this case, Atlas does not force us to learn about Web Service lingo such as WSDL, XML and proxy, etc in order to consume it. We have to remember the fact that there are so many people in the world who are not aware of technologies but have their own self managed portals and sites. They may just know that there are cool ‘some things’ known as web services that need to be utilized in their web pages. They may just know the fundamentals of javascript to provide a bit of WOW factor into their pages. Extensions such as Atlas, would sure be found useful by them. However, Atlas is not just for hobbyists but for developers too who want to improve their productivity by not just focusing on writing tons of script code again and again. They can channel their energies into develop more innovative web pages. In my view, Atlas can be equally used by both hobbyists and serious developers.
Here, I will explain how a web service can be consumed in the client side through javascript, from within an Atlas enabled page. When we use “AtlasWebSite” template in Visual Studio, the default.aspx file will be created as given below.
There is an Atlas component “ScriptManager” that you would see inside the form tags.
We have to reference the web service in this component, in order to create proxy for that service, so that we can consume that, in the javascript.
<atlas:ScriptManager ID="ScriptManager1" runat="server" >
<Services>
<atlas:ServiceReference GenerateProxy="true" Path="~/MyWebService.asmx" />
</Services>
</atlas:ScriptManager>
The following client-side function consumes the web service that we had referenced in the ScriptManager component of Atlas. As this web service is invoked asynchronously, by default, we require another callback method ( OnRequestCompleted in this example) to retrieve the result. An Html control – text box is created to let user type the input (the quote to be searched) to this web service. The result of the web service (name of the play, speaker and speech content) are updated in other html controls – text and text area.
<script language="javascript" type="text/javascript" >
function InvokeBiographyWebService()
{
var strInput = document.getElementById('textBoxName').value;
MyWebService.GetInfo(strInput, OnRequestCompleted);
}
function OnRequestCompleted(result)
{
var strContent = result.split("::");
document.getElementById('textBoxPlay').value = strContent[0];
document.getElementById('textBoxSpeaker').value = strContent[1];
document.getElementById('textAreaBio').value = strContent[2];
}
</script>
The following html pieces create the required Html controls for this application.
<input id="textBoxName" type="text" runat="server" style="width: 207px" value="Type content to be searched!!" />Run this application, and you will get the result displayed in text area of the page.
We should be aware of a fact that we can not make a call from client side script, to remote web service outside of the local site. In this example, I had used an excellent web service provided by xmlme (http://www.xmlme.com/WSShakespeare.asmx). In order to access this web service, I had created a local web service façade (MyWebService) that would in turn call that remote web service.
Now, you can compare this approach with the one that I had described in my previous blog – “Enhanced Client Side Functionalities in ASP.NET 2.0,,,”. However, we have just touched the tip of the iceberg. I will provide some more details on declarative programming model, javascript improvements and others of ASP.NET 2.0 AJAX extension, in my future blogs. Then we can honestly weigh it down with old and existing technologies.
Recently we had concluded doing a performance comparison between the latest BizTalk Server 2006 and the previous 2004 version. Needless to say that the results were in favor of BizTalk Server 2006 running on SQL Server 2005.
We were amazed at the percentage performance improvement that this new combination delivered in certain specific scenarios. For more details check here.
We have seen the significance of utilizing worker threads in user interface applications wherein responsiveness to the end user is of paramount importance. Proper usage of asynchronous pattern will yield not only better responsiveness but also better performance as well as scalability, since system’s critical resources such as threading are to be better utilized. However, a word of caution is, poor usage of threading might invariably lead to unpredictable (or highly predictable
) nightmare.
Both desktop and browser based applications would require asynchronous mechanism in order not to force the end users to stare philosophically at the blank (or filled with little incoherent content) screens too often and too long. While lack of any sort of responsiveness (or absence of any visible action) is a critical problem to both types of applications, sometimes, too much of responsiveness (or frequent dynamism) might also prove to be a nagging issue, specifically in web client applications. To be precise, I just mean frequently visible UI changes by the words “too much of responsiveness”.
The server centric web applications such as ASP.NET applications, based on its inherent request/response model and postback mechanism will have a bunch of pages that will be posted back to the server multiple times to carry out a business task.
The problems associated with this model are
i. Large amount of data is transmitted across wire, multiple times, unnecessarily. The famous postback mechanism transmits the data (all user inputs as well as the hidden viewstate data) to the server for processing. For example, if an employee id is all that is required to pull off the details about him/her from the server side, employee id is not just one input that flows into the server side, in this model.
ii. Server needs to do a lot of processing, time and again, for creating the content of whole page, by undergoing the ritualistic process of page building (remember HttpRuntime, Handlers, modules, page object etc).
iii. Rendering the whole page content for just to update its small portion will have unwarranted flickering effect on the user interface.
In the cases of high amount of performance and scalability requirements, first two points should pose a challenge and would get the attention from design and development team. Despite the fact that gauging how much pesky the issue that is related to third point is bit difficult ( as it depends on the characteristics of people that application is catering to
), this issue, in general, continues to be a point of frustration for web application developers and a point of irritation for seasoned web users.
So, how to tackle these problems that are offshoot of server centric, browser based web applications? Again asynchronous programming comes into picture to handle such issues. But, something more other than asynchronous mechanism is needed to tackle them. Enhanced client side functionalities in ASP.NET 2.0 are that something more.
What all required to handle these issues are that external server side call/a web request should be made from client side and server should respond to the client script by not discarding the content of the current page. Then a callback method from client side should be able to update a part of the page’s content through DHTML object model. It means that we do not try to eliminate the round trip to the server completely. But we try to eliminate transmitting unnecessarily large amount of data. Instead of a server control postbacks the web request; here a client side control tries to do that. But this request is of completely different type – callback request rather than to be a normal postback request. ASP.NET runtime understands this distinction so it will not do the significant task, of refresh the the page content completely as it generally does in normal requests. This fact is so important for eliminating the flickering effect or achieving the partial-rendering of the page. If I rephrase it correctly, this fact is so important for achieving the partial partial-rendering of the page
. Partial rendering of the page gets fully completed when server side sends the response of the callback page request to the client side script that updates the specific portion of the page by using DHTML object model.
I have developed a sample web page that executes a web service call and updates the result without causing the page to flicker through the usage of script callback mechanism.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
public partial class _Default : System.Web.UI.Page, ICallbackEventHandler
{
string resultStr = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("<script language=\"javascript\">");
sb.AppendLine();
sb.Append("function clientCallbackMethod(arg, context)");
sb.AppendLine();
sb.Append("{");
sb.AppendLine();
sb.Append("document.all['textAreaBio'].value = arg;");
sb.AppendLine();
sb.Append("}");
sb.AppendLine();
sb.Append("</script>");
sb.AppendLine();
Conceptually, an end user will initiate a call to server by activating certain event of an UI control in the web page. That triggered event should invoke a call to external server (in this sample, I do use local web service). Having processed that call, the server would return the result by calling back the client side method. Then the client side method should update the specific portion of the page. Overall, this task requires some action in both server and client side. If you think that we have to do all the plumbing that is required to achieve this task, fortunately it is not so. But, understanding of the plumbing work that is done automatically by .NET Fwk is very essential to appreciate the flexibility of .NET Fwk 2.0 as well as Atlas.
You would have noticed that I have implemented “ICallbackEventHandler” along with default “System.Web.UI.Page” class, in this page. This interface consists of two methods, RaiseCallbackEvent and GetCallbackResult that need to be implemented by us to execute some server side coding and get back the result. Now, these pieces, should be somewhat plumbed with client side scripting, as we would like to invoke server side calls in out of band way, so that result of this calls should not end up in refreshing the current page.
The key players in this code are methods of “ICallbackEventHandler” (“RaiseCallbackEvent” and “GetCallbackResult”), “GetCallbackEventReference” and “RegisterClientScriptBlock”.
“RegisterClientScriptBlock” method allows us to create the client script from within server side and register them for the page. In this sample, I have created three client script pieces that are nothing but the html code to create three HTML UI controls such as text box, button and text area. In fact, you can create them in Default.aspx page by dragging and dropping the html controls from tool box. But I did not want to clutter that design page as I wanted you to know how lot of extra coding is generated, consequently as the result of usage of the above mentioned methods. So, those are plain HTML controls, and clicking of the button after inputting a name into Html text box control, would show the biography content in another HTML control, text area.
when I click “Click!!!” button, that I have to get the input from text box control and pass that as a parameter to my web service call which supplies back the biography content. So, plumbing needs to be done between client side button event to server side web service call.
That plumbing is done through GetCallbackEventReference method. This method creates client side event handler code, by taking couple of parameters that provide information such as who implements the ICallbackEventHandler, what is the input value, what client side method is to be executed after a server side operation is completed, context to be passed, and whether this method will be invoked in asynchronous manner. See the following code snippet.string strCallbackScript = csm.GetCallbackEventReference(this, "document.all['textBoxName'].value", "clientCallbackMethod", null, true);
GetCallbackEventReference method will create the following piece of code (that you will see when you click on the view source option of context menu of the rendered web page) as a string.WebForm_DoCallback('__Page',document.all['textBoxName'].value,clientCallbackMethod,null,null,true)
This method, in fact performs the magic of sending out of band web request to the server from client side and that request, when it gets processed by the ASP.NET runtime, in turn, will invoke “RaiseCallbackMethod()” of current Page, as this is the one that implemented “ICallbackEventHandler”. “RaiseCallbackMethod()” will invoke the web service call, as given below.
public virtual void RaiseCallbackEvent(string eventArgs)If you are bit perplexed about how this WebForm_DoCallback() method has been wired with html button’s click event, See the code given below.
StringBuilder sbClickButton = new StringBuilder();Once the web service call is completed, “GetCallbackResult()” returns the result to the client side javascript method “clientCallbackMethod()” that I created and registered from server side. By clicking on the “View Source” option of web page’s context menu (by right clicking), you can see the script that I had registered.
<script language="javascript">
function clientCallbackMethod(arg, context)
{
document.all['textAreaBio'].value = arg;
}
</script>
Having received the result through its parameter “args”, “clientCallbackMethod()” updates the value in the text area control.
When most of the pieces are falling into their places, one may still wonder what that WebForm_DoCallback() really does in the back ground. Well, it is not acting all alone. I have given below the complete script created by the page, so that you can see various bits and pieces that are required but created automatically by the page. I have deleted some lines of script and realigned some, for clarity. But you can see the complete script through View Source option in the context menu of the rendered page.
<form name="form1" method="post" action="Default.aspx" id="form1">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGS0ExybgjnKXUzuLL5XZJnfITsM5A==" />
</div>
<script type="text/javascript">
<!--
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
// -->
</script>
<script src="/MyScriptCallbackWebSite/WebResource.axd?d=70lWo11C5EZPx_FfFXIoVg2&t=632964141447332273" type="text/javascript"></script>
<script language="javascript">
function clientCallbackMethod(arg, context)
{
document.all['textAreaBio'].value = arg;
}
</script>
<input id="textBoxName" type="text" runat="server" style="width: 207px" />
<input id="btnForTextBoxName" type="button" value="Click!!!" runat="server" onClick="javascript:WebForm_DoCallback('__Page',document.all['textBoxName'].value,clientCallbackMethod,null,null,true)" />
<br/>
<textarea id="textAreaBio" visible="false" style="width: 208px; height: 80px" ></textarea>
<script type="text/javascript">
<!--
WebForm_InitCallback();// -->
</script>
</form>
Don’t worry too much, if much of the content makes no sense, now. In fact, there is no need for us to know all these nitty-gritty. The fact is WebForm_DoCallback() method does the crucial work of sending an out of band web request to the server. When it does that, it includes lot of information in the request so that ASP.NET runtime would understand that this call is completely different from normal web requests and what to do further on this request. Then Http Handler will handle this request appropriately by invoking “RaiseCallbackEvent()” method, in the server side. The completion of this method will trigger the client side callback method “clientCallbackMethod()” and that would update the content in text area html control.
By this time you would have suspected the hands of XMLHTTP object which are somewhere hidden in this scene. Yes, WebForm_DoCallback() internally uses the XMLHTTP object and send the request to the server. ASP.NET provides a new spin to the whole story by abstracting the usage of XMLHTTP object and by hiding the tediousness associated with creating lot of plumbing javascript from the scratch.
For more internal details on it, please go through the excellent article in the link, http://msdn.microsoft.com/msdnmag/issues/04/08/CuttingEdge/
This approach using script callback mechanism eliminates the list of problems that I stated earlier as
i. only small amount of data is passed to the server side comparing to normal web request
ii. ASP.NET runtime also short-circuits the http handler mechanism to handle this specific callback request differently from normal postback based page requests
iii. it makes the partial rendering of a page, possible.
But story does not end here. ASP.NET 2.0 AJAX extensions, earlier code named Atlas, provide more flexibility in terms of creating visually appealing applications with less scripts to be crafted manually. An important thing to be noted down here is Atlas is not just a bunch of client side script code. It really steroids javascript through JSON (Javascript object notation) and provides a set of new controls and components (for both client and server side) with an AJAX script library that comprises the common development tasks. For example, Atlas would simplify the given code further as it supplies the control to call web services directly from client side code.
Working with Configuration files in .net fwk 1.1 was additionally supported by the Configuration block available as part of Enterprise Library (EL). With the release of .net fwk 2.0 and the introduction of System.Configuration subsystem, this is now becoming the way to work with configuration files. Hence EL 2.0 doesn't include a new Configuration block any more. Check this.
Working with System.Configuration via the Settings is quite simple with Visual Studio (VS) 2005. Check this article in case you need to know how to go about using it.
What I am going to talk about here is more in terms of how to bring in settings from libraries that you use in your code and merge with main application settings. Needless to say that any application one writes, will be using quite a few library components and without properly integrating their settings with the main application, things won't work as expected at runtime.
Lets build a sample application so as to help explain things properly. From VS2005, create a new Windows Application project. I called it SettingsDemo. Then I added another project to this same solution. The type of this was Class Library project and I called it CustomLibrary. Following this I added reference to the CustomLibrary project in my SettingsDemo project so that I could start using the library component. Adding project reference ensures build dependency and hence is better than directly adding reference to CustomLibrary.dll.
You will notice that the CustomLibrary component doesn't has a settings file under Properties. You can add one by either doing a "Add New Item" and select Settings file OR, you can go to Project properties and select Settings tab. It will prompt you to create a new settings file.
Once done, you can double click Settings.settings from Solution explorer, if not already open and start adding your own configuration values. For simplicity sake, I added two entries here String1 and String2 with Application scope and gave them some default values. I then added two public methods to the CustomControl to return the strings I just added. Sample code is as below
public string FirstMessage
{
get { return Settings.Default.String1; }
}
In order to use Settings in code, you will have to add using CustomLibrary.Properties; to the top. Go ahead and build the solution. Next I added two buttons on the Form1 in the SettingsDemo windows application project. In the Click event handlers for these buttons, I instantiated the CustomLibrary component and make a call to the public method. Sample code is as below
private void button1_Click(object sender, EventArgs e)
{
CustomLibrary.MyClass obj = new CustomLibrary.MyClass();
MessageBox.Show(obj.FirstMessage);
}
If you have been implementing alongside, you can build now and run the application. On the form that comes up, hit a button and you will see a message box display the string value added to the Settings.settings of CustomLibrary previously. So far so good, but the point of using Setting is the ability to change at run time. These values are expected to be part of the configuration file. However if you were to check the SettingsDemo\bin\debug folder, you won't find any.
If you have been implementing alongside, you can build now and run the application. On the form that comes up, hit a button and you will see a message box display the string value added to the of previously. So far so good, but the point of using Setting is the ability to change at run time. These values are expected to be part of the configuration file. However if you were to check the folder, you won't find any.So how did the code work? If you would go back to the solution explorer and navigate to Settings.designer.cs in the CustomLibrary project, and open it, you will notice that this file has two public methods and their names are same as the names we used in the Settings. Incidently, this is also the reason why we were able to access these via the Settings.Default.String1; call shown earlier. You will also notice that there is DefaultSettingValueAttribute and it has the value we entered for the setting in question earlier. The code (snapshot) in Settings.designer.cs would look something like below
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()][global::System.Configuration.DefaultSettingValueAttribute("This is string1")]
public string String1 {
get {
return ((string)(this["String1"]));
}
}
The ApplicationScopedSettingAttribute was added since we marked the setting as Application scope. If it is user scope, the attribute used will be UserScopedSettingAttribute. The DebuggerNonUserCodeAttribute is to mark this code as non-user code. In this case, this is wizard generated code. The final one DefaultSettingValueAttribute is the one that ensures that even when there isn't a configuration file present, there will still be a default value returned and prevent exceptions during code execution.
The was added since we marked the setting as Application scope. If it is user scope, the attribute used will be . The is to mark this code as non-user code. In this case, this is wizard generated code. The final one is the one that ensures that even when there isn't a configuration file present, there will still be a default value returned and prevent exceptions during code execution.If you are wondering that how do I change these values at runtime, since I can't be expected to edit this Settings.designer.cs file and rebuild everytime, you need to check out the app.config file in CustomLibrary project. This is where the entries are added and it is this file that you will modify at runtime to get the new values for your configurations. In my case the app.config file looks like below
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="CustomLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<CustomLibrary.Properties.Settings>
<setting name="String1" serializeAs="String">
<value>This is string1</value>
</setting>
<setting name="String2" serializeAs="String">
<value>This is string2</value>
</setting>
</CustomLibrary.Properties.Settings>
</applicationSettings>
</configuration>
When you build, you will also see CustomLibrary.dll.config getting created in CustomLibrary\bin\Debug folder. However this isn't copied to the SettingsDemo\bin\Debug folder and hence you aren't able to change the values at runtime. However don't get carried way and copy this file to SettingsDemo\bin\Debug for that doesn't help. You can give it a quick try. Copy the CustomLibrary.dll.config to this folder, edit it and make changes to the value of String1 or String2 setting and re-run the application. It will continue to show the old values.
This is where the merging comes into picture and for this we need to access the app.config file for SettingsDemo application. In case you don't see this file in solution explorer, you can add a new one via "Add New Item" and select Application Configuration file. It is in this file that we need to copy the entries done in app.config of CustomLibrary component. To easily follow how to make these entries, let first add a Setting to SettingsDemo project also. This will ensure that we already have entries in the App.config file for SettingsDemo project. I added a new setting called LocalString.
To this file we will add the CustomLibrary settings also. If you see the App.config file, you will see the <applicationSettings> section. It is in this section that the settings from CustomLibrary will be copied. You will also notice a subgroup <SettingsDemo.Properties.Settings> and likewise we will copy the entire section from CustomLibrary's app.config file to this. Additionally, to be able to read this newely added section, we need to make an entry to the <configSections><sectionGroup> group. Currently it is having an entry like <section name="SettingsDemo.Properties.Settings" ... and we need to add CustomLibrary.Properties.Settings. After modifications the file will look like as below (the bold faced text shows the additions done)
<?xml version="1.0" encoding="utf-8" ?>With this, now buid the application. Go to the SettingsDemo\bin\debug folder and open and edit the SettingsDemo.exe.config to make changes to the values of individual settings. Save and close the file and then run the SettingsDemo.exe from this folder. When you invoke the buttons, you will see the new values being displayed.
With this, now buid the application. Go to the folder and open and edit the to make changes to the values of individual settings. Save and close the file and then run the from this folder. When you invoke the buttons, you will see the new values being displayed.Note that after making changes to the SettingsDemo.exe.config, if you run from VS, it might end up overwritting your modified file, so it is best to directly run the EXE as I mentioned above.
Hope this helps. Get back to me in case of any questions.
Ever wondered how do you ever get intellisense while writing configuration files in the XML Config editor using VS?
Ever seen that Warning message which we comfortably ignore and which says “Could not find schema for the element <some_custom_config_section>”?
This is why.
All the schemas for VS are defined at C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas\
Look for the file DotNetConfig.xsd
You can make changes to it, to add your own elements which will show up in intellisense in the VS Config file editor.
If you have your own schema definitions which you want to employ at an enterprise level, then you can add them to this file, so that you stop getting those irritating warning messages, as well as exploit the power of Intellisense for your custom config sections.
But make sure you have a backup of the original file before you mess anything up.
Recently when trying to work programmatically with BizTalk rules, I noticed that the RuleSetDeploymentDriver class appears twice, once in the Microsoft.RuleEngine namespace and once in Microsoft.BizTalk.RuleEngineExtensions. Not able to figure out what to use where, I dropped a mail to Sreedhar. In his response he indicated that when calling the policies from a generic Winform application, one should use Microsoft.RuleEngine.RuleSetDeploymentDriver and when working with BizTalk, one should use Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver.
He said that he will update the documentation and I did notice a new blog on his site about this.
There was this interesting decision someone from a technical team had to make. Given a long list of n values to be searched, would you use Linear Search, or a Binary Search after a Quick Sort. For a given value of n, which is the most efficient search method?
Lets look at some Math.Time taken by a Linear Search over n items is O(n)
Time taken by a Binary Search over n item is O(log2n)
Time taken to sort n items is O(n x log2n)
To simplify, for a value of n = 256,
An indicative Linear Search time for 1 search operation O(n) is: 383
An indicative Binary Search time for 1 search operation O(n x log2n) + O(log2n) is: 2048 + 8 = 2056
After 100 search operations over the same set of items this value becomes,
Linear Search: 383 x 100 = 38300
Binary Search: 2048 (because sort is performed only once) + 8x100 = 2848
Interestingly the decision is not based on the size of n. But rather on the number of Search operations on the item space. Linear Search is fast if the amount of search operations are lesser. When the amount of search operations made on the list increases, the time taken to sort is mitigated (the goodies of economies of scale plays its part in algorithms as well) and Binary Search results as the better option.
Ideally, the choice between Linear and Binary Search should be taken based on the number of search operations that are likely to be performed over the List.
A very useful .NET Type that can come in handy in this situation is SortedList. SortedList is a collection of key/value pairs that are sorted automatically by the keys, as you add items to it. This way you can let the framework sort stuff for you, just before you run a Binary Search.
Recently a person put forth a query that he has written a custom control, overridden from an existing control, and using it in a Winform application. He was assigning some default values for some of the properties in the control's constructor. First time he added that control to the Winform, it showed the default values properly, however when we edited the custom control, recompiled and ran the Winform application again, the control instance on the form still showed the old value.
What was he doing wrong? For some of the properties of the base control like Text, this was working but for some like BackColor, this wasn't.
Looking at the typical Winform code, you will see that in the Form's .cs code, a call being made to InitializeComponent in the constructor. If you are working with .net fwk 2.0, the implementation of this function will be in the form's designer.cs file. A quick analysis of this method reveals the reason for the above stated problem.
All the controls being used on the forms are first instantiated and then further in code, each control's properties and their assigned values are listed. For example
this.MyCustomControl1 = new MyCustomControl();
//
// MyCustomControl1
//
this.MyControlControl1.BackColor = System.Drawing.Color.Blue;
This means that when the form is loaded, it will first call the control's constructor and then assign the value of the BackColor property to a value of Blue. This code was generated since this control had a property BackColor and it was being initialized to Blue in the constructor. So if we can get this assignement to a value of Blue removed from the form's InitializeComponent method, when we change the value in the control's constructor, and rebuild it, it should work fine.
This is handled by using an attribute with the property. The property that you don't want to get persisted to the designer, should be tagged with the following attribute
[System.ComponentModel.DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
There are other options for the DesignerSerializationVisibility enum. You can check the documentation for details on the values. Marking this as hidden, ensures that when the control is added to a form, the particular property value isn't serialized in the InitializeComponent method. Now you can go ahead and easily make changes to the property values in the control's constructor and everytime you run the application, the value being assigned in the constructor is what will get used.
Hope this helps. If you have questions, drop me a mail