<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D0MGQ3k7fSp7ImA9WxBXFkk.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705</id><updated>2010-01-28T03:23:42.705+01:00</updated><title>Javi's technical blog</title><subtitle type="html">Random thoughts on .NET and other technologies</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://javiercrespoalvez.com/" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/JavisTechnicalBlog" /><feedburner:info uri="javistechnicalblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>JavisTechnicalBlog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FJavisTechnicalBlog" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FJavisTechnicalBlog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FJavisTechnicalBlog" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/JavisTechnicalBlog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FJavisTechnicalBlog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FJavisTechnicalBlog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FJavisTechnicalBlog" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:browserFriendly>(Enter a personal message you would like to have appear at the top of your feed.)</feedburner:browserFriendly><entry gd:etag="W/&quot;DUMDQ3g4eCp7ImA9WxVVEE8.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-8007209115250908290</id><published>2009-03-02T21:52:00.001+01:00</published><updated>2009-03-02T21:57:52.630+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-02T21:57:52.630+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL Service Broker" /><title>Using SQL Service Broker in NET applications</title><content type="html">&lt;p&gt;I've been doing some work with SQL Service Broker lately and I thought I could speak about my experience with it. I was interested in the possibility of using &lt;a href="http://www.nservicebus.com/" target="_blank"&gt;NServiceBus&lt;/a&gt; or any other popular implementation of a Enterprise Service Bus in .NET (&lt;a href="http://code.google.com/p/masstransit/" target="_blank"&gt;MassTransit&lt;/a&gt;, &lt;a href="http://ayende.com/Blog/archive/2008/12/17/rhino-service-bus.aspx" target="_blank"&gt;RhinoServiceBus&lt;/a&gt;) with an underlying transport different from Msmq and I thought SQL Service Broker could be a good candidate for the replacement.&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;This implementation exercise shouldn't be a very complicated&amp;nbsp; task taking into account the great deal of extensibility of a framework like NServiceBus (you just need to implement an interface called ITransport to start using your own transport layer along with the bus), but unfortunately up to this point of time there is no API implementation for Service Broker in .NET framework so things get a bit trickier. Actually, while dealing with the implementation of a custom API for Service Broker I've hit some limitations/design decisions which, in my opinion, make SQL Broker not the best option for the transport layer of an Enterprise Service Bus framework.&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;&lt;b&gt;Distributed Transactions&lt;/b&gt;&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;I don't want to get into the details about how SQL Service Broker works, but if you have ever used it, you know that messages are retrieved from queues using the TSQL instruction &lt;a href="http://msdn.microsoft.com/en-us/library/ms186963.aspx" target="_blank"&gt;RECEIVE&lt;/a&gt; which is a not blocking call but you can combine it with the &lt;a href="http://msdn.microsoft.com/en-us/library/ms187331.aspx" target="_blank"&gt;WAITFOR&lt;/a&gt; command for the blocking effect so you avoid polling the queue for dealing with new coming messages. The main problem with WAITFOR instruction is that it sets a transaction savepoint which makes the current transaction not suitable for enlistment; putting it in other words the message handling from the queue cannot be used in the context of a distributed transaction. &lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;So what's the big deal? Actually, I read in msdn forums that SQL broker team wants to discourage the use of distributed transactions because of their performance hit. Besides, you might argue that you can get by without DT keeping all the work related to the message handling in the same database and so there is no need for enlistment. I'm afraid this covers some scenarios but it falls short in others, you have to bear in mind that:&lt;/p&gt;&lt;br&gt; &lt;ul&gt; &lt;li&gt;Not every transactional resource is a SQL Server instance, it doesn't even need to be a SQL engine at all  &lt;li&gt;Even if all your transactional resources are SQL Server instance because of scalability you might have to keep queues in a different instance from where your mainstream/business data is.  &lt;li&gt;Regarding security you might have to use different sql user accounts to handle messages and handle application data&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;For all these scenarios distributed transactions are needed to provide reliable message handling and avoid situations like repeated or lost messages...Can you imagine a bank system where messages that increase/decrease account balance could be handled twice or not handled at all??&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;There is an alternative provided by SQL Broker that could help to get around this limitation (apart from polling)&amp;nbsp; called External Activation which in few words is sort of a SQL trigger where custom logic can be placed to be executed upon messages arrival to a queue. Then the trick is to use a second queue to store notifications of new coming messages so the consumer application reads and waits from this event queue out of transaction and when a new message arrives it doesn't need to use WAITFOR to go to the main queue to receive the real message within a transaction. I think that this overcomplicates things as you have to handle two queues for what you could do with one and you have to make sure that both queues stay in sync so for example you don't face situations where there are messages outstanding in the main queue and available consumers to handle them but the messages don't get served because the event queue is empty.&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;&lt;b&gt;Poison messages handling&lt;/b&gt;&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;An aspect that has to be always taken into account while developing a messaging solutions is the poison messages handling and the replayable message strategy. A valid strategy would be that, on the event of error during message handling, retry up to n times and after it goes over the limit the message can be sent to a dead/error message queue.&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;But what do we do when there is an error while handling the message, for example an external subsystem needed for processing the message is down for some time? A straight forward answer would be to rollback the current transaction so all inconsistent business work would be undone and the current message would come back to the queue so it could be handled again later when maybe the subsystem would come back (you can keep counters at message level for the retries to identify poison messages).&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;Well this strategy clashes with the way SQL Service Broker deals with poison messages: A queue is disabled upon 5 consecutive times transaction rollbacks when RECEIVE is used... Once the queue is disabled it cannot be used for processing until an user with administrator right enables it back. This automatic poison message detection it's not message bound, it can't be disabled and the number of consecutive times can't even be changed!&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;To sum up, on one hand we should always try to commit the transaction to avoid this behavior to be triggered but on the other hand we don't want to leave our business data in a inconsistent state, which leads us to split up the transaction in two: one for the message and the other for the business logic; pretty much we are back to square one with the risk of repeated/lost messages...&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;There are a couple of ways around that behavior though, one of them is another sort of a trigger where custom logic can be placed to be executed upon queue disabled event. The other one is to follow the strategy explained &lt;a href="http://msdn.microsoft.com/en-us/library/ms171592.aspx" target="_blank"&gt;here&lt;/a&gt;, which in few words consists of creating a transaction savepoint (bye bye distributed transaction again) before receive is executed and rollback from that transaction savepoint in case of error, so technically the receive statement is not rollbacked.&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;&lt;b&gt;Wrapping up&lt;/b&gt;&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;Despite the issues above, I think that this has been a good experience as I have got to know better SQL Broker and I've had the chance to dig a bit into NServiceBus internals and understand a bit more how it works under the hood.&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;The general idea that I get of SQL Broker is that it can be a good solution in an applications where the message handling business logic is included in the database, but for .NET applications I'd rather go for MSMQ queues which, on top of providing an API implementation in .NET framework, don't suffer from the problems that I've talked about.&amp;nbsp; &lt;p&gt;I'm no expert in SQL Broker though, so if I'm missing something, don't hesitate to say it, I'll appreciate it!&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjaviercrespoalvez.com%2f2009%2f03%2fusing-sql-service-broker-in-net.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjaviercrespoalvez.com%2f2009%2f03%2fusing-sql-service-broker-in-net.html&amp;amp;bgcolor=3E700F&amp;amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-8007209115250908290?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/8007209115250908290/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2009/03/using-sql-service-broker-in-net.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8007209115250908290?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8007209115250908290?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/m824K-kBedo/using-sql-service-broker-in-net.html" title="Using SQL Service Broker in NET applications" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2009/03/using-sql-service-broker-in-net.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4HQ3k_fyp7ImA9WxVWGEw.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-6555578377070408543</id><published>2009-02-28T09:47:00.001+01:00</published><updated>2009-02-28T09:48:52.747+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-28T09:48:52.747+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Other" /><title>Moving this blog to a custom domain</title><content type="html">&lt;p&gt;I’ve moved this Blogger blog to the custom domain that you can see in your navigation bar, the former blogspot url will keep redirecting to the new domain though.&lt;/p&gt;&lt;br/&gt; &lt;p&gt;You may already know that a new domain means a new PageRank, and as I have already noticed in the traffic figures of this site, a poorer PageRank :) (you can read about this subject &lt;a href="http://www.consumingexperience.com/2007/08/domain-name-change-search-engine.html" target="_blank"&gt;here&lt;/a&gt;).&lt;/p&gt;&lt;br/&gt; &lt;p&gt;So my advice is that if you have a blog engine subdomain url&amp;nbsp; (blogger, wordpress, etc) and you are thinking of going for your own custom domain, the sooner the better!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-6555578377070408543?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/6555578377070408543/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2009/02/moving-this-blog-to-custom-domain.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/6555578377070408543?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/6555578377070408543?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/ylluGbyoSSM/moving-this-blog-to-custom-domain.html" title="Moving this blog to a custom domain" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2009/02/moving-this-blog-to-custom-domain.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIGQns8eCp7ImA9WxVXEk0.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-3373657009666169907</id><published>2009-02-09T20:14:00.000+01:00</published><updated>2009-02-09T20:25:23.570+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-09T20:25:23.570+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><title>ASP.NET Custom Button Controls Source Code</title><content type="html">&lt;p&gt;I’ve uploaded the source code of the &lt;a href="http://javiercrespoalvez.com/2008/12/aspnet-confirmation-button-using-jquery.html" target="_blank"&gt;Confirmation Button control&lt;/a&gt; &lt;a href="http://sites.google.com/site/javicrespotech/Home/ConfirmButtonSample.zip" target="_blank"&gt;here&lt;/a&gt; and the &lt;a href="http://javiercrespoalvez.com/2009/01/aspnet-multiple-validation-group-button.html" target="_blank"&gt;Multiple Validation Group Button control&lt;/a&gt; &lt;a href="http://sites.google.com/site/javicrespotech/Home/MultipleValidationGroupButtonSample.zip" target="_blank"&gt;here&lt;/a&gt;. Besides, for the former I have fixed a bug regarding ASP.NET validation and I have extended the original javascript file to support confirmation popups on html link clicks, and for the latter I have created a separate library project with the custom controls and their associated javascript embedded.&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;Any feedback will be welcomed!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-3373657009666169907?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/3373657009666169907/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2009/02/aspnet-custom-button-controls-source.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/3373657009666169907?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/3373657009666169907?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/8cIKVI8Wxyg/aspnet-custom-button-controls-source.html" title="ASP.NET Custom Button Controls Source Code" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2009/02/aspnet-custom-button-controls-source.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcDQHY9fSp7ImA9WxVXEk0.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-32927838058682564</id><published>2009-01-11T21:58:00.000+01:00</published><updated>2009-02-09T20:01:11.865+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-09T20:01:11.865+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><title>ASP.NET Multiple Validation Group Button</title><content type="html">&lt;p&gt;In ASP.NET validation controls, the Validation Group allows to break down the set of page validation controls into different units that can be executed independently from each other. Then, a single validation group can be specified at button level so a particular action is glued to a validation controls subset. There are some situations though, where you might be interested in binding a button to multiple validation groups, one of these situations is described in &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=102994" target="_blank"&gt;this feedback entry at Microsoft Connect site&lt;/a&gt;.&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;That was back in 2005 when the Validation Group concept was a brand new upcoming feature in .NET 2.0, which by that time was still in beta version. Well, despite the fact that guys from Microsoft seemed to be receptive to the suggestion, it's 2009, ASP.NET is in it 3.5 version and we all know that this feature hasn't quite made it :(. The workaround suggested is to call &lt;em&gt;Page.Validate(group)&lt;/em&gt; in server-side but then it means that we'd need to ditch client-side validation which I'm not very happy about. &lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;p&gt;So let's pick up this suggestion and create a new asp.net button control that includes a coma delimited validation group list property.&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MultipleValidationGroupButton: Button&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;{&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// Gets or sets the validation group list&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// comma delimited.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;value&amp;gt;The validation group list.&amp;lt;/value&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// Empty string represents validation controls that&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// don't define validation group property&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ValidationGroupList&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  { &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;      get &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      { &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; ViewState[&lt;span style="color: #006080"&gt;"ValidationGroupList"&lt;/span&gt;] &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;      set &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      { &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          ViewState[&lt;span style="color: #006080"&gt;"ValidationGroupList"&lt;/span&gt;] = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnPreRender(EventArgs e)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValidationGroupList))&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.CausesValidation = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; script = String.Format(&lt;span style="color: #006080"&gt;"ValidateGroups('{0}','{1}');"&lt;/span&gt;, &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;              &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValidationGroupList);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Page.IsAsyncPostBack())&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;              ScriptManager.RegisterStartupScript(Page, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Page), &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID, script, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;              Page.ClientScript.RegisterStartupScript(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Page), &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID, script, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;     &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.OnPreRender(e);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// Validates the groups.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ValidateGroups()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;  {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValidationGroupList))&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;      {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[] list = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValidationGroupList.Split(&lt;span style="color: #006080"&gt;','&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;          &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; list)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;          {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;              Page.Validate(item);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;          }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;      }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;  }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The server side implementation is pretty straightforward: we check if the &lt;em&gt;ValidationGroupList&lt;/em&gt; propety has been set and if so we disable the regular ASP.NET validation mechanism (&lt;em&gt;CausesValidation=false&lt;/em&gt;) and we register the call to the script that will actually do the job (For the client-side registration I use the &lt;em&gt;Page.IsAsyncPostBack&lt;/em&gt; partial method already implemented while creating &lt;a href="http://javicrespotech.blogspot.com/2008/12/aspnet-confirmation-button-using-jquery.html" target="_blank"&gt;my jQuery ConfirmationButton&lt;/a&gt;). The purpose of &lt;em&gt;ValidateGroups&lt;/em&gt; method is to remove the need of hardcoding the validation groups in code behind to enforce server side validation, so instead of doing this:&lt;/p&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Button_Click(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;{&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;   Page.Validate(&lt;span style="color: #006080"&gt;"Group1"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;   Page.Validate(&lt;span style="color: #006080"&gt;"Group2"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;   Page.Validate(&lt;span style="color: #006080"&gt;"Group3"&lt;/span&gt;); &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;   &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Page.IsValid)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;   { &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;       &lt;span style="color: #008000"&gt;//Button Actions&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;   }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;We don’t need to scatter our validation groups in both markup and code-behind because we can do this:&lt;/p&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Button_Click(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;{&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;   &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Button.ValidateGroups();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Page.IsValid)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;   { &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;       &lt;span style="color: #008000"&gt;//Button Actions&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;   }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;And to end with, server-side wise, this is how we define our button in ASP.NET markup language.&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;div&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;cc:MultipleValidationGroupButton&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="btn"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="server"&lt;/span&gt; &lt;br /&gt;        &lt;span style="color: #ff0000"&gt;ValidationGroupList&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Group1,Group2"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;onclick&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Button_Click"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Click"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br&gt;&lt;br /&gt;&lt;p&gt;Now it's time to code the javascript function that performs validation on button click. For the implementation, I've used some of the syntactic sugar that jQuery offers but as I'm not using a great deal of things of it you could potentially rewrite this function with plain javascript without much complexity, although I must say that after you start using jQuery (if you haven't yet), you will never want to go back to plain javascript again!&lt;/p&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; ValidateGroups(buttonId, validationGroupList) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #008000"&gt;//Bind the logic to the specified button with jQuery&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    $(&lt;span style="color: #006080"&gt;"#"&lt;/span&gt; + buttonId).click(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(e) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; list = validationGroupList.split(&lt;span style="color: #006080"&gt;','&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #008000"&gt;//Loop through the entire set of page validators&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        $.each(Page_Validators, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.validationGroup &amp;amp;&amp;amp; ExistsGroup(list, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.validationGroup)) &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            ||(!&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.validationGroup &amp;amp;&amp;amp; ExistsGroup(list, &lt;span style="color: #006080"&gt;''&lt;/span&gt;))) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                ValidatorValidate(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.validationGroup);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;                Page_IsValid = Page_IsValid &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.isvalid;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        });&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #008000"&gt;//Reflect validation in ValidationSummary's if there are any in the page&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        $.each(list, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            ValidationSummaryOnSubmit(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        });&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #008000"&gt;//If Page_IsValid is false the execution flow will be interrupted&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Page_IsValid;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    });&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; ExistsGroup(list, group) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; found = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; list.length; i++) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (list[i] == group) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            found = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; found;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;And that’s it, the implementation is ready but before we wrap it up, there are a few things that are worth mentioning: The second clause in the if statement is there to support the scenario where we would potentially want to combine “ungrouped” with “grouped” validation controls and in that situation we’d define our control like this:&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt;&lt;div&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;cc:MultipleValidationGroupButton&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="btn"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="server"&lt;/span&gt; &lt;br /&gt;        &lt;span style="color: #ff0000"&gt;ValidationGroupList&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=",Group1"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;onclick&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Button_Click"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Click"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br&gt;&lt;br /&gt;&lt;p&gt;Finally, you may have noticed that I've used extensively the ASP.NET validation client-side API (&lt;em&gt;ValidatorValidate&lt;/em&gt;, &lt;em&gt;Page_Validators&lt;/em&gt;, etc), if you want to have more details about this API I recommend you using our friend Reflector to get acquainted to this library (System.Web assembly, Resources folder, WebUIValidation.js resource), that helped me a lot.&lt;/p&gt;&lt;br&gt;&lt;br /&gt;&lt;p&gt;Hope this helps!&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;UPDATE: &lt;/b&gt;I've uploaded the code for this post &lt;a href="http://sites.google.com/site/javicrespotech/Home/MultipleValidationGroupButtonSample.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;br&gt;I've created a library project with ASP.NET custom controls for Button, ImageButton and LinkButton; the associated javascript code is embedded in that project (apart from jQuery js file).&lt;br&gt;&lt;br&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2009%2f01%2faspnet-multiple-validation-group-button.html"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2009%2f01%2faspnet-multiple-validation-group-button.html&amp;amp;bgcolor=3E700F&amp;amp;cbgcolor=CAF99B" border="0"&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-32927838058682564?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/32927838058682564/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2009/01/aspnet-multiple-validation-group-button.html#comment-form" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/32927838058682564?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/32927838058682564?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/wZwEgWatVlc/aspnet-multiple-validation-group-button.html" title="ASP.NET Multiple Validation Group Button" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">12</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2009/01/aspnet-multiple-validation-group-button.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QHR3kzeyp7ImA9WxVaE00.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-4205363731246981026</id><published>2008-12-14T22:19:00.000+01:00</published><updated>2009-04-09T20:22:16.783+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-09T20:22:16.783+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JQuery" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><title>ASP.NET Confirmation Button using JQuery</title><content type="html">&lt;p&gt;Quite often in business applications the use of confirmation modal popups is required in order to get confirmation from the user of a specific action he’s going to carry out. In web environment the “gorgeous” built-in javascript confirm function is a valid option, but we are living in the XXI century and we can do much better! Particularly with JQuery and the &lt;a href="http://www.ericmmartin.com/projects/simplemodal/"&gt;SimpleModal&lt;/a&gt; plug-in we can achieve something like this with very little effort:&lt;/p&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://lh6.ggpht.com/_rIotvlm4gjQ/SUU8zBo09tI/AAAAAAAAADs/edFV7yEr96c/s1600-h/Confirmation%5B9%5D.jpg"&gt;&lt;img title="Confirmation" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="147" alt="Confirmation" src="http://lh3.ggpht.com/_rIotvlm4gjQ/SUU8zVEs-4I/AAAAAAAAADw/Gv8uAob0qX0/Confirmation_thumb%5B5%5D.jpg?imgmax=800" width="425" border="0"&gt;&lt;/a&gt; &lt;br&gt; &lt;p&gt;So, let's get started! First of all we’ll download jQuery js file, SimpleModal js file and css file and add references to them in our master page:&lt;/p&gt;&lt;br&gt;&lt;br&gt; &lt;div&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;script&lt;/span&gt; &lt;span style="color: #ff0000"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/Sample/Scripts/jquery-1.2.6.js"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;script&lt;/span&gt; &lt;span style="color: #ff0000"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/Sample/Scripts/SimpleModal/jquery.simplemodal.js"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='text/css'&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='/Sample/Scripts/SimpleModal/css/confirm.css'&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='stylesheet'&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br&gt;Then we can create the actual html that will be used as modal popup. The html will be reused in any call to the jQuery plugin so we’ll put it in the master page anywhere within the body tag. &lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='confirm'&lt;/span&gt; &lt;span style="color: #ff0000"&gt;style&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='display: none'&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='header'&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;asp:Literal&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="ConfirmLiteral"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="server"&lt;/span&gt; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="&amp;lt;%$ Resources:Global, Confirm %&amp;gt;"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;p&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='message'&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='buttons'&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='no modalClose'&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;asp:Literal&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="NoLiteral"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="server"&lt;/span&gt; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="&amp;lt;%$ Resources:Global, No %&amp;gt;"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;='yes'&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;asp:Literal&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="YesLiteral"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="server"&lt;/span&gt; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                    &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="&amp;lt;%$ Resources:Global, Yes %&amp;gt;"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;If you don’t need to localize the popup, of course you can get rid of the resources and the Literal controls. Now we can create the javascript function that uses the plugin to show the modal popup.&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; confirm(message, callbackYes) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;   $(&lt;span style="color: #006080"&gt;'#confirm'&lt;/span&gt;).modal({&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        close:&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        overlayId:&lt;span style="color: #006080"&gt;'confirmModalOverlay'&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        containerId:&lt;span style="color: #006080"&gt;'confirmModalContainer'&lt;/span&gt;, &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        onShow: &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (dialog) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            dialog.data.find(&lt;span style="color: #006080"&gt;'.message'&lt;/span&gt;).append(message);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            &lt;span style="color: #008000"&gt;// if the user clicks "yes"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            dialog.data.find(&lt;span style="color: #006080"&gt;'.yes'&lt;/span&gt;).click(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                &lt;span style="color: #008000"&gt;// call the callback&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ($.isFunction(callbackYes)) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                    callbackYes.apply();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;                }  &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                &lt;span style="color: #008000"&gt;// close the dialog&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;                $.modal.close();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            });&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;We already have the means to show the popup but we still need to trigger it on button clicked.&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; Page_IsValid = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; SetConfirmation(buttonId, message)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;{&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    $(&lt;span style="color: #006080"&gt;"#"&lt;/span&gt; + buttonId).click(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(e) {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #008000"&gt;//We keep the original click event so&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #008000"&gt;//it can be executed as a callback&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; target = $(e.target);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #008000"&gt;//We prevent the form from posting back&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        e.preventDefault();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(Page_IsValid)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            confirm(message,&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() {target.click();});&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    });&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The SimpleModal plugin provides asynchronous and non-blocking functionally (not like the builtin javascript confirm) and that means that we need to prevent the original button’s click event from happening (e.preventDefault();) but at the same time we need to keep it as a callback function to be used in case the user confirms the action to be executed (e.target.click();). &lt;/p&gt;&lt;br /&gt;&lt;p&gt;If we you are using ASP.NET validators you might want to show the confirmation pop up only the page is valid (Page_IsValid), there is no point of asking for confirmation if the action cannot be carried out anyways! The variable initialization outside the function guarantees that our function won’t break if there is no ASP.NET validator in the page.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Well, client-side wise we are done, here it goes a usage sample.&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;SetConfirmation(&lt;span style="color: #006080"&gt;'&amp;lt;%= myButton.ClientID %&amp;gt;'&lt;/span&gt;,&lt;span style="color: #006080"&gt;'Are you sure of this?'&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Let’s focus on server-side now, is there anything we can do? Well, we can create a asp.net control that hides the javascript event subscription to the consumer, so dropping this line in the Page/UserControl markup would be enough to have the confirmation button functionality all in a single place.&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;sample:ConfirmButton&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="actionButton"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="server"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="&amp;lt;%$ Resources:Global, Action %&amp;gt;"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt; &lt;span style="color: #ff0000"&gt;OnClick&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="actionButton_Click"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Message&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="&amp;lt;%$ Resources:Global, ConfirmationMessage %&amp;gt;"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Here goes the implementation of the ConfirmButton control&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ConfirmButton : Button&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;{&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Message&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        get;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        set;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnPreRender(EventArgs e)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.OnPreRender(e);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Message))&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; script = String.Format(&lt;span style="color: #006080"&gt;"SetConfirmation('{0}','{1}');"&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Message);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Page.IsAsyncPostBack())&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                ScriptManager.RegisterStartupScript(Page, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Page), &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID, script, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;            &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;                Page.ClientScript.RegisterStartupScript(type, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ClientID, script , &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;A few things to point out in the implementation: the javascript call is only rendered if a message text has been assigned to the control, which means that we could potentially use the ConfirmButton as our regular button and provide the confirmation message only when needed.&amp;nbsp; The second thing is that we could extract a helper method from the logic in the OnPreRender method, so we could use this helper method to set confirmations programmatically upon any sort of button control (Button, ImageButton, LinkButton). Finally, note that the ScriptManager has to be used to register the javascript in the page when the control is rendered as a part of an UpdatePanel partial postback. The following page extension method is defined to identify those scenarios.&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; PageExtensions&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;{&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsAsyncPostBack(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; Page page)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        var result = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        var scriptManager = ScriptManager.GetCurrent(page);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(scriptManager != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;            result = scriptManager.IsInAsyncPostBack;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;        }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; result;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;    }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;p&gt;And that's it, I hope this helps!&lt;/p&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;UPDATE: &lt;/b&gt;You can find the code of this post &lt;a href="http://sites.google.com/site/javicrespotech/Home/ConfirmButtonSample.zip?attredirects=0"&gt;here&lt;/a&gt;&lt;br&gt;Besides, I've added some code to enable confirmation popup on link click and I've fixed a bug regarding validation.&lt;/p&gt;&lt;br/&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;UPDATE #2:&lt;/b&gt;I've updated the javascript code in order to fix an issue that I ran into when using the confirmation buttons with Update Panels (The javascript event handler binder was getting executed on every partial post back which was causing some issues with the popup callback. Check out &lt;a href="http://sites.google.com/site/javicrespotech/Home/ConfirmButtonSample.zip?attredirects=0"&gt;the implementation&lt;/a&gt; for more details, all the changes I did are documented in the js file)&lt;/p&gt;&lt;br&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f12%2faspnet-confirmation-button-using-jquery.html"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f12%2faspnet-confirmation-button-using-jquery.html&amp;amp;bgcolor=3E700F&amp;amp;cbgcolor=CAF99B" border="0"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-4205363731246981026?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/4205363731246981026/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/12/aspnet-confirmation-button-using-jquery.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/4205363731246981026?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/4205363731246981026?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/9Azjd8NmdKI/aspnet-confirmation-button-using-jquery.html" title="ASP.NET Confirmation Button using JQuery" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">8</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/12/aspnet-confirmation-button-using-jquery.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYHQ3w5fip7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-3575707341406910354</id><published>2008-12-08T23:41:00.007+01:00</published><updated>2008-12-08T23:58:52.226+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-08T23:58:52.226+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Team Foundation Server" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous integration" /><title>Team Build notification on test failed</title><content type="html">&lt;p&gt;A nice feature in a Continuous Integration environment is the ability to notify developers (or even managers yuk!) when a build breaks. The command Biisubscribe in TFS 2008 allows to hook up email alerts on build completion, for example this is how we can configure &lt;a href="http://www.codeplex.com/VSTSGuidance/Wiki/View.aspx?title=How%20to%20receive%20notification%20when%20a%20build%20has%20failed&amp;amp;referringTitle=Build%20Practices%20at%20a%20Glance"&gt;email notifications on build failure due to compilation errors&lt;/a&gt;: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 8pt; PADDING-BOTTOM: 0px; MARGIN: 0em; OVERFLOW: visible; WIDTH: 100%; COLOR: black; BORDER-TOP-STYLE: none; LINE-HEIGHT: 12pt; PADDING-TOP: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; BORDER-BOTTOM-STYLE: none"&gt;bissubscribe /eventType BuildCompletionEvent /address myemail@domain.com&lt;br /&gt;/deliveryType EmailPlaintext /server tfsserver1&lt;br /&gt;/filter "TeamProject = &lt;span style="color:#006080;"&gt;'MyTeamProject'&lt;/span&gt; AND CompletionStatus=&lt;span style="color:#006080;"&gt;'Failed'&lt;/span&gt;“&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;If you are running tests as a part of the build process though, you might want to take it to the next level and send notifications when any of your tests has failed. Tests are one of the most important pieces of a Continuous integration environment and as such they deserve to be taken in consideration in the notification process :)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In TFS 2008 “Failed” builds are builds that have failed during compilation time while “Partial Succeeded” builds are builds that have gone through the compilation process correctly but have failed in any of the post build actions… such as the test runner! So we have all the info needed to modify the filter from the previous command and get notifications when our tests fail :&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 8pt; PADDING-BOTTOM: 0px; MARGIN: 0em; OVERFLOW: visible; WIDTH: 100%; COLOR: black; BORDER-TOP-STYLE: none; LINE-HEIGHT: 12pt; PADDING-TOP: 0px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; BORDER-BOTTOM-STYLE: none"&gt;bissubscribe /eventType BuildCompletionEvent /address myemail@domain.com&lt;br /&gt;/deliveryType EmailPlaintext /server tfsserver1&lt;br /&gt;/filter "TeamProject = &lt;span style="color:#006080;"&gt;'MyTeamProject'&lt;/span&gt; AND&lt;br /&gt;         (CompletionStatus=&lt;span style="color:#006080;"&gt;'Failed'&lt;/span&gt; OR CompletionStatus=&lt;span style="color:#006080;"&gt;'Partially Succeeded'&lt;/span&gt;)“ &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Hope this helps!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f12%2fteam-build-notification-on-test-failed.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f12%2fteam-build-notification-on-test-failed.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-3575707341406910354?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/3575707341406910354/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/12/team-build-notification-on-test-failed.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/3575707341406910354?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/3575707341406910354?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/gAlGVLJl4Iw/team-build-notification-on-test-failed.html" title="Team Build notification on test failed" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/12/team-build-notification-on-test-failed.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUCRH06eCp7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-8080596857609943595</id><published>2008-09-25T12:23:00.007+02:00</published><updated>2008-12-09T00:01:05.310+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:01:05.310+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Castle" /><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><title>Singleton WCF Proxy</title><content type="html">In WCF, creating a proxy is a heavy operation, so if you are experiencing performance slowdown you should definitely look at this area. One of the possible solutions to tackle this problem is to reuse your proxies across your application threads, either implementing a singleton or a pool, but in any case bear in mind that proxy reusability is only advisable in some scenarios (see &lt;a href="http://blogs.msdn.com/wenlong/archive/2007/10/26/best-practice-always-open-wcf-client-proxy-explicitly-when-it-is-shared.aspx"&gt;this&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx"&gt;this&lt;/a&gt; for the considerations).&lt;br /&gt;Ok, so let's say that we want to go for a singleton proxy and we use Castle as a DI container to handle the proxy instances.&lt;br /&gt;In theory the implementation would be as easy as this&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="TestService"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="WCFTest.Contracts.ITestService, WCFTest.Contracts"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="WCFTest.Proxies.TestProxy, WCFTest.Proxies"&lt;/span&gt; &lt;br /&gt;                  &lt;span class="attr"&gt;lifestyle&lt;/span&gt;&lt;span class="kwrd"&gt;="singleton"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Where ITestService is the WCF contract and TestProxy is the proxy for that contract... End of the story? Not quite. The problem here arises when for any reason the channel associated to the proxy gets faulted. You probably already know that &lt;a href="http://jeffbarnes.net/portal/blogs/jeff_barnes/archive/2007/04/24/wcf-your-proxy-can-only-fault-once.aspx"&gt; a faulted proxy can no longer connect to a service&lt;/a&gt; and in order to connect again to it there is no option than throwing away the faulted proxy instance and using a new one.&lt;br /&gt;So it seems that the singleton approach doesn't suit our needs; we need to find a way of recreating proxy instances only when a proxy is in faulted state, something like &lt;a href="http://bloggingabout.net/blogs/erwyn/archive/2006/12/09/WCF-Service-Proxy-Helper.aspx"&gt;this approach&lt;/a&gt; but fit in our DI container. Good news is that Castle gives the possibility to &lt;a href="http://castleproject.org/container/documentation/trunk/usersguide/lifestyles.html"&gt;define custom lifestyle managers for our instances&lt;/a&gt;; we just need to implement the ILifestyleManager interface (or like in the following code snippet, the abstract class AbstractLifestyleManager) and provide the expected behavior.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// Singleton WCF Proxy Lifestyle Manager&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SingletonWCFProxyLifestyleManager : AbstractLifestyleManager&lt;br /&gt;{&lt;br /&gt;    &lt;span class="preproc"&gt;#region&lt;/span&gt; properties&lt;br /&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; instance;&lt;br /&gt;    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="preproc"&gt;#region&lt;/span&gt; overriden methods&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Resolves the specified instance from the context.&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="context"&amp;gt;The context.&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;The resolved object&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Resolve(Castle.MicroKernel.CreationContext context)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;lock&lt;/span&gt; (&lt;span class="kwrd"&gt;base&lt;/span&gt;.ComponentActivator)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//If the instance does not exists it is resolved&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.instance == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.instance = &lt;span class="kwrd"&gt;base&lt;/span&gt;.Resolve(context);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                ICommunicationObject communicationObject = &lt;span class="kwrd"&gt;this&lt;/span&gt;.instance &lt;span class="kwrd"&gt;as&lt;/span&gt; ICommunicationObject;&lt;br /&gt;                &lt;span class="rem"&gt;//If the proxy is in faulted state, it's aborted and&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;//a new proxy is created&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (communicationObject != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp;&lt;br /&gt;                    communicationObject.State == CommunicationState.Faulted)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;                    {&lt;br /&gt;                        communicationObject.Abort();&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;catch&lt;/span&gt; { }&lt;br /&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;this&lt;/span&gt;.instance = &lt;span class="kwrd"&gt;base&lt;/span&gt;.Resolve(context);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.instance;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Releases unmanaged and - optionally - managed resources&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.instance != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;base&lt;/span&gt;.Release(&lt;span class="kwrd"&gt;this&lt;/span&gt;.instance);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Releases the specified instance.&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="instance"&amp;gt;The instance.&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Release(&lt;span class="kwrd"&gt;object&lt;/span&gt; instance)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Then we need to change the objects configuration file to use our custom implementation.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="TestService"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="WCFTest.Contracts.ITestService, WCFTest.Contracts"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="WCFTest.Proxies.TestProxy, WCFTest.Proxies"&lt;/span&gt; &lt;br /&gt;                  &lt;span class="attr"&gt;lifestyle&lt;/span&gt;&lt;span class="kwrd"&gt;="custom"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;customLifestyleType&lt;/span&gt;&lt;span class="kwrd"&gt;="WCFTest.Common.SingletonWCFProxyLifestyleManager, WCFTest.Common"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Well, I hope that if you are using Castle to manage singleton WCF proxies, this post will be helpful.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f09%2fsingleton-wcf-proxy.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f09%2fsingleton-wcf-proxy.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-8080596857609943595?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/8080596857609943595/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/09/singleton-wcf-proxy.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8080596857609943595?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8080596857609943595?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/PoY0_9FIv-M/singleton-wcf-proxy.html" title="Singleton WCF Proxy" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/09/singleton-wcf-proxy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08BSXo6eip7ImA9WxdUEUU.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-3770613807739657916</id><published>2008-07-23T20:37:00.006+02:00</published><updated>2008-07-27T20:04:18.412+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-27T20:04:18.412+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ADO.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Certifications" /><title>ADO.NET 3.5 certification exam results</title><content type="html">Back in April I blogged about my experience sitting for &lt;a href="http://javicrespotech.blogspot.com/2008/04/adonet-35-certification-exam.html"&gt;the new ADO.NET 3.5 exam beta&lt;/a&gt;. Well, Microsoft published last week the results for this exam and for &lt;a href="http://www.microsoft.com/learning/en/us/exams/70-562.mspx"&gt;ASP.NET 3.5&lt;/a&gt; one too, and I'm glad to say that I passed; here it goes my new logo :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_rIotvlm4gjQ/SIy1uHYNczI/AAAAAAAAACk/nedU14cDNAA/s1600-h/MCTS(rgb)_1101.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_rIotvlm4gjQ/SIy1uHYNczI/AAAAAAAAACk/nedU14cDNAA/s320/MCTS(rgb)_1101.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5227753071329506098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These exams should be live shortly, so if you are interested in taking them, you might want to check out &lt;a href="http://blogs.msdn.com/gerryo/"&gt;Gerry's blog&lt;/a&gt; for the latest news.&lt;br /&gt;Btw, I highly recommend taking &lt;a href="http://vishaljoshi.blogspot.com/2005/11/microsoft-beta-exams.html"&gt;beta exams&lt;/a&gt;: they help to keep up to and discover new technologies and they have the advantage of being free of charge!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-3770613807739657916?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/3770613807739657916/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/07/adonet-35-certification-exam-results.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/3770613807739657916?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/3770613807739657916?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/5Do0Nl1f73s/adonet-35-certification-exam-results.html" title="ADO.NET 3.5 certification exam results" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp3.blogger.com/_rIotvlm4gjQ/SIy1uHYNczI/AAAAAAAAACk/nedU14cDNAA/s72-c/MCTS(rgb)_1101.gif" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/07/adonet-35-certification-exam-results.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQESXY5eCp7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-2101747307881781947</id><published>2008-07-07T20:05:00.005+02:00</published><updated>2008-12-09T00:01:48.820+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:01:48.820+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Team Foundation Server" /><title>TFS wish list</title><content type="html">I've been using TFS 2008 for a while, and despite the new good features (easier installation, offline support, better build management, built-in continuous integration, etc), I'm a little bit disappointed to see that some limitations existent in the previous TFS 2005 haven't been solved yet in this new release.&lt;br /&gt;Don't get me wrong; I think that TFS is a great product but, moving forward, this would be my wish list for the following TFS version, &lt;a href="http://msdn.microsoft.com/en-us/vstudio/bb725993.aspx"&gt;codename Rosario&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Server Side Check-in policies&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/team_foundation/archive/2005/04/15/408700.aspx"&gt;Checkin policies&lt;/a&gt; are a very nice feature in TFS; for example you can enforce that before anyone checks a changeset in, he has to associate it with a Work item, or he's had to build the solution and run FxCop, etc... The concept is good, but I don't like the way that it has been implemented: Checkin policies are enforced at &lt;strong&gt;client side&lt;/strong&gt; rather than at &lt;strong&gt;server side&lt;/strong&gt; and this has some bad implications, for example the inconvenience of deploying custom checkin policies.&lt;br /&gt;TFS explorer comes along with some policies but as you may have expected you can create your own custom policies; actually you might want to check the policies that &lt;a href="http://msdn.microsoft.com/en-us/tfs2008/bb980963.aspx"&gt;TFS 2008 Power tools&lt;/a&gt; provides before creating a new one.&lt;br /&gt;So far so good, the catch is that after getting one way or another your custom policy, in order to enforce it, you have to make sure that everyone in your team deploys it in his workstation or it won't be run when they check in and, on top of that, they will get a nasty policy loading error :( As you can see &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1987073&amp;amp;SiteID=1"&gt;here&lt;/a&gt;, there are people out there that have the same frustration...&lt;br /&gt;I've been focusing in the inconvenience of deployment that this client-side model implies, but what about security? So what if a developer decides to change any of the policies implementation to disable check-in validation?... Well, you might be wondering why somebody would want to do that, but if check-in policies were enforced at server side you wouldn't be wondering.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;TFS application tier running in a 64bit box&lt;/strong&gt;&lt;br /&gt;There is not much to say about this, the header text is self explanatory :)&lt;br /&gt;Even if you go for a non single server deployment where you could use a x64 for the data tier (SQL Server), TFS application tier still needs to be installed in a x32 bit machine...&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Branching: carry source history to the branch&lt;/strong&gt;&lt;br /&gt;As Brendan Lawlor pointed out &lt;a href="http://blog.decaresystems.ie/index.php/2007/04/18/more-limitations-of-tfs-branching/"&gt;here&lt;/a&gt;, when a branch is created in TFS 2005, its history starts from its creation point of time so the branch doesn't "remember" any of the changes that were made on its source.&lt;br /&gt;This means, for example, that comparing a changeset from the branch against a change made back in time on the head becomes a non straightforward task, especially if you happen to be in a situation where nested branches are required. &lt;br /&gt;Unfortunately, after a simple test in TFS 2008, you will notice that this problem hasn't been solved yet.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;TFS event subscription GUI tool&lt;/strong&gt;&lt;br /&gt;It would be great if TFS came along with a proper GUI tool to handle subscriptions for events remotely, something like this &lt;a href="http://www.codeplex.com/tfseventsubscription"&gt;open source tool&lt;/a&gt; provides but not only limited to work item events. &lt;br /&gt;Even for something so simple like sending a notification email when a build fails the TFS Project Alerts screen is useless so you have to end up using the &lt;a href="http://www.codeplex.com/VSTSGuidance/Wiki/View.aspx?title=How%20to%20receive%20notification%20when%20a%20build%20has%20failed&amp;referringTitle=Build%20Practices%20at%20a%20Glance"&gt;bissubscribe command tool&lt;/a&gt;, which by the way can only be run locally on the TFS application server. &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;That was my list; feel free to post your own thoughts and comments about it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f07%2ftfs-wish-list.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f07%2ftfs-wish-list.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-2101747307881781947?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/2101747307881781947/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/07/tfs-wish-list.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/2101747307881781947?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/2101747307881781947?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/2NuvJwAB4Ts/tfs-wish-list.html" title="TFS wish list" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/07/tfs-wish-list.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQGSH04eSp7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-649751404535355212</id><published>2008-06-08T14:47:00.011+02:00</published><updated>2008-12-09T00:02:09.331+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:02:09.331+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Castle" /><category scheme="http://www.blogger.com/atom/ns#" term="AOP" /><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><category scheme="http://www.blogger.com/atom/ns#" term="Enterprise Library" /><title>Dependency Injection in WCF Services Part 4</title><content type="html">In the &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services_17.html"&gt;last post of these series&lt;/a&gt;, I showed a first approach on how to use Castle Interceptors along with WCF Castle Facility to apply cross-cutting concerns in the Service Layer. The Log sample interceptor that I used for this last post was hopefully enough to get the flavour, but I think that a more compelling sample is needed to demonstrate what these interceptors are really capable of. &lt;br /&gt;I won't leave the Enterprise Library though, but instead of the Logging Application Block I'll use the Validation Application Block for this demo.&lt;br /&gt;&lt;br /&gt;Let's take the sample that I've been using in these series and add a Save function in the Customer Service.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Service&lt;br /&gt;{&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerService:ICustomerService&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; properties&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; ICustomerDataAccess customerDataAccess;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ICustomerDataAccess CustomerDataAccess&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; customerDataAccess; }&lt;br /&gt;            set { customerDataAccess = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer GetCustomer(&lt;span class="kwrd"&gt;long&lt;/span&gt; id)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; CustomerDataAccess.GetCustomer(id);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer SaveCustomer(Customer customer)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; customerDataAccess.SaveCustomer(customer);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And the unrealistically simple Customer class goes as follows&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Entity&lt;br /&gt;{&lt;br /&gt;    [DataContract]&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Customer&lt;br /&gt;    {&lt;br /&gt;        [DataMember]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CustomerId { get; set; }&lt;br /&gt;        [DataMember]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; String Name { get; set; }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Now we need to meet the requirement that for saving a Customer its Name must be at least 5 characters long and it cannot be longer than 35 characters... The Validation Application Block gets into the game!&lt;br /&gt;&lt;br /&gt;The Validation Application Block added value is that it provides a central repository of rules that can be used across the entire application layers so we don't end up coding the same rule in UI, Service, Data Access...&lt;br /&gt;&lt;br /&gt;The rules can be defined either in configuration files or through .NET attributes; for this sample I'll use the latter, particularly, the StringLengthValidator through its attribute.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Entity&lt;br /&gt;{&lt;br /&gt;    [DataContract]&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Customer&lt;br /&gt;    {&lt;br /&gt;        [DataMember]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CustomerId { get; set; }&lt;br /&gt;        &lt;br /&gt;        [StringLengthValidator(5, 35)]&lt;br /&gt;        [DataMember]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; String Name { get; set; }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The validator is already declared, but we still need to kick it off. The Enterprise Library provides some API helper methods to instatiate validators so as to fire them, for now we'll put that code in the Service implementation.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerService:ICustomerService&lt;br /&gt;  {&lt;br /&gt;      ....&lt;br /&gt;      &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;      ......&lt;br /&gt;      &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer SaveCustomer(Customer customer)&lt;br /&gt;      {&lt;br /&gt;          ValidationResults validation = Validation.ValidateFromAttributes&amp;lt;Customer&amp;gt;(customer);&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (!validation.IsValid)&lt;br /&gt;              &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; InvalidOperationException();&lt;br /&gt;&lt;br /&gt;          &lt;span class="kwrd"&gt;return&lt;/span&gt; customerDataAccess.SaveCustomer(customer);&lt;br /&gt;      }&lt;br /&gt;      &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;And the validation requirement is already fulfilled with this code. If we follow this approach though, we would need to produce a similar code snippet for every method in the service and for each parameter that a method receives. In other words, this looks like a situation where an interceptor would be more than welcome :)&lt;br /&gt;&lt;br /&gt;Let's remove the validation code from the Save method and create the ValidationInterceptor class.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Interceptor&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ValidationInterceptor:IInterceptor&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; IInterceptor Members&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Intercept(IInvocation invocation)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;object&lt;/span&gt; argument &lt;span class="kwrd"&gt;in&lt;/span&gt; invocation.Arguments)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (argument != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    Validator validator = ValidationFactory.CreateValidator(argument.GetType());&lt;br /&gt;                    ValidationResults result = validator.Validate(argument);&lt;br /&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!result.IsValid)&lt;br /&gt;                        &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; InvalidOperationException();&lt;br /&gt;                }&lt;br /&gt;                &lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;As easy as it looks; input parameters are available through the Arguments property of the IInvocation interface so we just need to loop through them and use Enterprise Library Helper methods to fire the validators. &lt;br /&gt;&lt;br /&gt;You may have noticed that I haven't been very informational throwing an InvalidOperationException with no message; however it would be pretty straightforward to create a custom Exception that will carry the information that the Enterprise Library ValidationResult class provides.&lt;br /&gt;&lt;br /&gt;We are almost done, the only thing left is to declare the validation interceptor through Castle configuration file&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerService"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.CustomerService, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;interceptors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;interceptor&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;${ValidationInterceptor}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;interceptor&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;interceptors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="ValidationInterceptor"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Interceptor.ValidationInterceptor, DISample.Interceptor"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerDataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.ICustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.CustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;So before any method of the Customer class gets call, our interceptor will verify the correctness of the input parameters according to the rules defined through the Validation Application Block. No wonder that there is room for many improvements in that code, but the point that I was trying to make is that the task of apply cross cutting concerns gets much simpler using Castle Interceptors and Enterprise Library Application blocks.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f06%2fdependency-injection-in-wcf-services.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f06%2fdependency-injection-in-wcf-services.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-649751404535355212?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/649751404535355212/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/06/dependency-injection-in-wcf-services.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/649751404535355212?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/649751404535355212?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/twbclfFFDvw/dependency-injection-in-wcf-services.html" title="Dependency Injection in WCF Services Part 4" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/06/dependency-injection-in-wcf-services.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQASHk6eip7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-8073004784918248640</id><published>2008-05-22T22:00:00.010+02:00</published><updated>2008-12-09T00:02:29.712+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:02:29.712+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server" /><category scheme="http://www.blogger.com/atom/ns#" term="Code generation" /><title>Unique Index Schema Information in SQL Server</title><content type="html">Unique indexes along foreign key constraints are used to model One-To-One relationships in Database model design. In fact, when it comes to the DB design, the only difference between a One-To-One relationship and a One-To-Many relationship is that Unique index. For Data Access code generation purposes the existence of the unique index will effectively tell you, for example if you are generating navigation properties, whether to create a simple entity type navigation (One-To-One) or an entity array type navigation (One-To-Many) between the two entities that take part in the data base relationship.&lt;br /&gt;&lt;br /&gt;In ADO.NET the &lt;a href="http://msdn.microsoft.com/en-us/library/ms254969.aspx"&gt;GetSchema methods&lt;/a&gt; can be used to get Schema information from different Data base provider types; unfortunately for SQL Server Databases unique index information is not provided with that API. Don't panic though, one way or another SQL Server hast to store the unique index information in its catalog tables so after digging into the master database views list for a while, we bump into the table sys_indexes and its is_unique column. An index can be applied upon many columns therefore we'll need to join with sys.index_columns and sys.columns in order to get the column name as well.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; c.[name] &lt;span class="kwrd"&gt;as&lt;/span&gt; column_name, a.[name] &lt;span class="kwrd"&gt;as&lt;/span&gt; index_name, is_unique &lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; sys.indexes a &lt;span class="kwrd"&gt;INNER&lt;/span&gt; &lt;span class="kwrd"&gt;JOIN&lt;/span&gt; sys.index_columns b &lt;br /&gt;&lt;span class="kwrd"&gt;ON&lt;/span&gt; a.object_id = b.object_id &lt;span class="kwrd"&gt;AND&lt;/span&gt; a.index_id = b.index_id &lt;br /&gt;&lt;span class="kwrd"&gt;INNER&lt;/span&gt; &lt;span class="kwrd"&gt;JOIN&lt;/span&gt; sys.columns c &lt;br /&gt;&lt;span class="kwrd"&gt;ON&lt;/span&gt; b.object_id = c.object_id &lt;span class="kwrd"&gt;and&lt;/span&gt; b.column_id = c.column_id &lt;br /&gt;&lt;span class="kwrd"&gt;WHERE&lt;/span&gt; a.object_id = OBJECT_ID(N&lt;span class="str"&gt;'dbo.yourTable'&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2funique-index-schema-information-in-sql.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2funique-index-schema-information-in-sql.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-8073004784918248640?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/8073004784918248640/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/05/unique-index-schema-information-in-sql.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8073004784918248640?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8073004784918248640?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/RY5k6MfLIiU/unique-index-schema-information-in-sql.html" title="Unique Index Schema Information in SQL Server" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/05/unique-index-schema-information-in-sql.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQDQX05eCp7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-5588110575247026541</id><published>2008-05-17T13:15:00.005+02:00</published><updated>2008-12-09T00:02:50.320+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:02:50.320+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="Castle" /><category scheme="http://www.blogger.com/atom/ns#" term="AOP" /><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><category scheme="http://www.blogger.com/atom/ns#" term="Enterprise Library" /><title>Dependency Injection in WCF Services Part 3</title><content type="html">In the &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services.html"&gt;first post of these series&lt;/a&gt;, I explained the problems you may run into when applying Dependency Injection in your distributed service layer, and in the &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services_03.html"&gt;second one&lt;/a&gt; I put the theory in practice using &lt;a href="http://www.castleproject.org/container/facilities/trunk/wcf/index.html"&gt;Castle Windsor WCF Facility&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now that our DI container instantiates our services, we can take advantage of other features not necessarily related to Dependency Injection available in the container. Particularly in this post I'll drift away a bit from dependency injection and I'll focus on the interception capabilities that Castle Windsor framework offers.&lt;br /&gt;&lt;br /&gt;Let's take the sample that I've been using for these series and say for example that we want to use Enterprise Library Application Loggin Block so as to log every method execution in our service object.&lt;br /&gt;A simple implementation would be to include the logging call in the service implementation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Service&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerService:ICustomerService&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; properties&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; ICustomerDataAccess customerDataAccess;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ICustomerDataAccess CustomerDataAccess&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; customerDataAccess; }&lt;br /&gt;            set { customerDataAccess = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer GetCustomer(&lt;span class="kwrd"&gt;long&lt;/span&gt; id)&lt;br /&gt;        {&lt;br /&gt;            Logger.Write(&lt;span class="str"&gt;"GetCustomer Start"&lt;/span&gt;);&lt;br /&gt;            Customer customer = CustomerDataAccess.GetCustomer(id);&lt;br /&gt;            Logger.Write(&lt;span class="str"&gt;"GetCustomer End"&lt;/span&gt;);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; customer;&lt;br /&gt;        }&lt;br /&gt;   &lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;So we are leaving the logging responsability to the service class itself... That doesn't sound quite right, does it? The service responsability is to interact with the Data Access layer and/or carry out business process but logging is a cross cutting concern that has nothing to do with the actual service implemenation. Besides, for the sake of code cleanignless and reusability, in my Service code I don't want stuff that is not related to the Service main purpose.&lt;br /&gt;&lt;br /&gt;Then, how we can possibly achieve logging in our service object leaving the logging calls out of our service implementation? Well, we might use &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;the Decorator pattern&lt;/a&gt; for that. This pattern gives the ability to extend the functionality of a class without changing its orginal implementation.&lt;br /&gt;Let's create the CustomerServiceLogginDecorator logging decorator in order to include logging capabilities to our service.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Service&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerServiceLoggingDecorator:ICustomerService&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; properties&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; ICustomerService customerService;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ICustomerService CustomerService&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; customerService; }&lt;br /&gt;            set { customerService = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer GetCustomer(&lt;span class="kwrd"&gt;long&lt;/span&gt; customerId)&lt;br /&gt;        {&lt;br /&gt;            Logger.Write(&lt;span class="str"&gt;"GetCustomer Start"&lt;/span&gt;);&lt;br /&gt;            Customer customer = CustomerService.GetCustomer(customerId);&lt;br /&gt;            Logger.Write(&lt;span class="str"&gt;"GetCustomer End"&lt;/span&gt;);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; customer;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Notice that the decorator implements the same interface that our service implementation; that's the whole point of the Decorator pattern. The service consumers use the service through its interface (ICustomerService) and it's through the DI container that we specify a particular service implementation for that interface. Therefore, we can create our decorator as a service frontend and inject the actual service implementation into the decorator.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerService"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.&lt;span style="color:#ff0000;"&gt;CustomerServiceLoggingDecorator&lt;/span&gt;, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerServiceImpl"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.CustomerService, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerDataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.ICustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.CustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Notice as well that, since the decorator uses ICustomerService interface as dependency, the underlying implementation of the service remains hidden and therefore we can use the DI container to inject as many ICustomerService decorators as we wish upon the real service implementation. Let's imagine that we want to add an exception decorator...&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerService"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.&lt;span style="color:#ff0000;"&gt;CustomerServiceExceptionDecorator&lt;/span&gt;, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerServiceLogging"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.&lt;span style="color:#ff0000;"&gt;CustomerServiceLoggingDecorator&lt;/span&gt;, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerServiceImpl"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.CustomerService, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerDataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.ICustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.CustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, so we got it, there are no longer cross cutting concerns in my service implementation but probably you´ll have already realized that this solution is not the best either. If we carried on with this approach we'd need to create a decorator for each cross cutting concern in each service, it means that we could end up with a number of decorator classes up to (number of Services)*(number of cross cutting concerns) = let´s call this idea off now!&lt;br /&gt;&lt;br /&gt;Well, it looks like the Decorator Pattern can be the way but we need something to remove from us the burden of creating for a single aspect a bunch of service specific decorators. Fortunately, castle framework comes to our rescue and offers us &lt;a href="http://www.castleproject.org/container/documentation/trunk/usersguide/interceptors.html"&gt;the Interceptor functionality&lt;/a&gt; which allows to create independent and reusable cross cutting concern implementations.&lt;br /&gt;Let´s create our reusable logging interceptor.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Castle.Core.Interceptor;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Practices.EnterpriseLibrary.Logging;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; DISample.Interceptor&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LogginInterceptor:IInterceptor&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; IInterceptor Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Intercept(IInvocation invocation)&lt;br /&gt;        {&lt;br /&gt;            Logger.Write(invocation.Method.Name + &lt;span class="str"&gt;" Start"&lt;/span&gt;);&lt;br /&gt;            invocation.Proceed();&lt;br /&gt;            Logger.Write(invocation.Method.Name + &lt;span class="str"&gt;" End"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And to start using it, we just have to define it in the castle configuration file.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerService"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.CustomerService, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;interceptors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;interceptor&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;${LoginInterceptor}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;interceptor&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;interceptors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="LoginInterceptor"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Interceptor.LoginInterceptor, DISample.Interceptor"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerDataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.ICustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.CustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;That's great, isn't it? We define independent interceptors that can be applied upon any class regardless of its type; Castle will take care of the call flow an interception for us.&lt;br /&gt;&lt;br /&gt;To that's it, we have used Castle framework to apply cross cutting concerns in our WCF Service... But that's not what WCF Custom Behaviours are for? Yes, Custom Behaviours get injected in the WCF call stack and in there you can implement some aspects not related to your service implementation like logging, catching, transaction handling, etc. Besides the &lt;a href="http://msdn.microsoft.com/en-us/library/aa480453.aspx"&gt;Enterprise Library 3.1&lt;/a&gt; comes along with a set of Custom Behaviors for WCF that are nothing more that thin wrappers upon the Application Blocks like the &lt;a href="http://msdn.microsoft.com/en-us/library/cc309334.aspx"&gt;Validation Block Custom Behavior&lt;/a&gt;. Then, why would we want to build Castle Interceptors if we can use the Enterprise Library WCF custom Behaviors?.&lt;br /&gt;&lt;br /&gt;Thinking in terms of the overall application and not only about the service layer, you might decide to apply cross cutting concerns to your web layer, your controller layer, your data access layer, etc. and for that WCF Custom Behaviours have no use. The bottom line is that if you want to use a unique homogeneous mechanish to handle cross cutting concers across all your application layers, WCF Custom Behaviours are not the solution!&lt;br /&gt;&lt;br /&gt;Having said that, in the next post of these series I'll show how to implement a more sophisticated Interceptor than the Logging one I explained in this post; Particularly I'll show what it takes to implement an equivalent of the Enterprise Library WCF Validation Custom Behaviour in a Castle Interceptor.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fdependency-injection-in-wcf-services_17.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fdependency-injection-in-wcf-services_17.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-5588110575247026541?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/5588110575247026541/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/05/dependency-injection-in-wcf-services_17.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/5588110575247026541?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/5588110575247026541?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/zcFgL34lMb8/dependency-injection-in-wcf-services_17.html" title="Dependency Injection in WCF Services Part 3" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/05/dependency-injection-in-wcf-services_17.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMEQnk8fyp7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-1800364193211564221</id><published>2008-05-10T12:20:00.007+02:00</published><updated>2008-12-09T00:03:23.777+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:03:23.777+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JSON" /><category scheme="http://www.blogger.com/atom/ns#" term="WebServices" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><title>JSON services in ASP.NET Ajax</title><content type="html">Lately the use of client centric development model in .NET is getting increasingly popular. In contrast to the traditional server model where html tags are rendered in server side and then sent to the browser, the client centric approach consist of the use of asynchronous HTTP requests to retrieve data from server side and then do the html rendering in client side code.&lt;br /&gt;&lt;br /&gt;The main advantage of this client centric approach is that the communication between the browser and the server gets much lighter; the browser doesn't need to post the page to get information from the server, it rather issues asynchronous calls to Web Services, which implement the JSON protocol, for retrieving the data. You might be wondering why XML-SOAP or other XML based RPC protocols are not used instead of that JSON...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt; is a non-markup based language which has some limitations comparing to XML languages (i.e: lack of namespaces) but that simplicity makes it lighter, easier to handle by browsers, and overall more performant and more suitable for this web client scenario.&lt;br /&gt;&lt;br /&gt;Unfortunately there is a catch :( ; since the rendering is done in client side, you'd better forget about using your automatically rendered ASP.NET controls and be prepared to start messing around extensively with javascript code for the rendering... No need to go through that pain though, there are some third party client based controls that implement rendering through javascript libraries, particularly you might want to check what &lt;a href="http://www.codeplex.com/AjaxDataControls"&gt;this open source control library&lt;/a&gt; can offer you.&lt;br /&gt;&lt;br /&gt;Well, now that we have gone through the theory, how can we put that in practice in ASP.NET? How can we implement and consume a JSON service?&lt;br /&gt;ASP.NET Ajax framework provides some built-in mechanisms to handle JSON communication and serialization automatically.&lt;br /&gt;These mechanisms are &lt;strong&gt;Page Methods&lt;/strong&gt;, &lt;strong&gt;Ajax Web Services&lt;/strong&gt; and &lt;strong&gt;Ajax WCF Services&lt;/strong&gt; and I'm going to spend the rest of this post to do a brief walkthrough on them.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Page methods&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A page method is a static function marked as a web method and declared within the page code behind. This function can be called from javascript code through a predefined class/keyword called &lt;strong&gt;PageMethods&lt;/strong&gt;. Let's take a look in a sample step by step.&lt;br /&gt;&lt;br /&gt;First the Page method execution has to be enabled in the asp.net ScriptManager.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="scriptManager"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;EnablePageMethods&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Now it's time to implement the static web method in the page's code behind.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; _Default : System.Web.UI.Page&lt;br /&gt;{&lt;br /&gt;    [WebMethod]&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; String ToUpper(&lt;span class="kwrd"&gt;string&lt;/span&gt; name)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; name.ToUpper();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Finally, the method is consumed from a script included in the page. As I said before the call execution follows an asynchronous pattern, therefore in the sample below if the operation succeds the resulting string in upper case is passed to the OnSucceded method, otherwise the OnFailed method receives the .NET exception.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; ToUpper(name)&lt;br /&gt;{&lt;br /&gt;    PageMethods.ToUpper(name, OnSuccedeed, OnFailed);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; OnSuccedeed(res)&lt;br /&gt;{&lt;br /&gt;    alert(res);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; OnFailed(error)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;// Alert user to the error.&lt;/span&gt;&lt;br /&gt;    alert(error.get_message());&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Web Services&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;One of the main differences between Page Methods and Ajax Web Services is that Page Methods can only be used by a single Page and Web Services can be used from as many pages as it’s needed. Needlees to say, both Ajax Web Services and Page Methods use JSON as communication protocol. Let's rework the previous example to use Web Services.&lt;br /&gt;&lt;br /&gt;First the HTTP Handler that will serve AJAX Web services requests and responses needs to be included in the web.config file.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;httpHandlers&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;remove&lt;/span&gt; &lt;span class="attr"&gt;verb&lt;/span&gt;&lt;span class="kwrd"&gt;="*"&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;="*.asmx"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;verb&lt;/span&gt;&lt;span class="kwrd"&gt;="*"&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;="*.asmx"&lt;/span&gt; &lt;span class="attr"&gt;validate&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Next step is to create a web service, which I'll call StringHandler.asmx. The Web Service's class needs to be marked with the ScriptService attribute and ToUpper web method to be implemented.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; JsonServicesSample&lt;br /&gt;{&lt;br /&gt;    [ScriptService]&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; StringHandler : System.Web.Services.WebService&lt;br /&gt;    {&lt;br /&gt;        [WebMethod]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ToUpper(String input)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; input.ToUpper();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;We are getting there, now it's just to include the server through the ScriptManager...&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="ScriptManager1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ServiceReference&lt;/span&gt;&lt;br /&gt;          &lt;span class="attr"&gt;Path&lt;/span&gt;&lt;span class="kwrd"&gt;="~/StringHandler.asmx"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;and everything is ready to retrieve data from the client script.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; ToUpper(name)&lt;br /&gt;{&lt;br /&gt;    JsonServicesSample.StringHandler&lt;br /&gt;    .ToUpper(name, OnSuccedeed, OnFailed);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; OnSuccedeed(res)&lt;br /&gt;{&lt;br /&gt;    alert(res);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; OnFailed(error)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;// Alert user to the error.&lt;/span&gt;&lt;br /&gt;    alert(error.get_message());&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;WCF Services&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The .NET 3.5 framework release came along with some fixes and extensions upon the early WCF .NET 3.0 version; one of those extensions is the webHttpBinding binding which implements JSON serialization and communication protocol.&lt;br /&gt;So for those who use VS2008 and .NET 3.5 let's rework the sample for the last time.&lt;br /&gt;&lt;br /&gt;First of all the service implementation has to be changed to include the WCF contract attributes; for the sake of simplicity I won't create a separate interface for the contract, I'd rather apply the contract attributes in the implementation itself.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; JsonServicesSample&lt;br /&gt;{&lt;br /&gt;    [ServiceContract&lt;br /&gt;        (Namespace=&lt;span class="str"&gt;"JsonServices.Contract.Sample"&lt;/span&gt;)]&lt;br /&gt;    [AspNetCompatibilityRequirements(&lt;br /&gt;            RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; StringHandler : System.Web.Services.WebService&lt;br /&gt;    {&lt;br /&gt;        [OperationContract]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ToUpper(String input)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; input.ToUpper();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On top of the WCF contract attributes, the &lt;strong&gt;AspNetCommpatibilityRequirements&lt;/strong&gt; attribute is provided. That attribute will allow the WCF service to have access to the HTTP context (i.e.: ASP.NET Session variable) and besides, it will tell the runtime to ensure at Service Host creation time that all the enpoints defined for the JSON contract use the Web http binding.&lt;br /&gt;Now it's time to define the service and its endpoint in Web.config file, notice that the AspNetCompatibilityRequirements attribute needs to be defined at the ServiceHost level as well.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.serviceModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;behaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;endpointBehaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;behavior&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="StringHandlerBehavior"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;enableWebScript&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;behavior&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;endpointBehaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;behaviors&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;serviceHostingEnvironment&lt;/span&gt; &lt;span class="attr"&gt;aspNetCompatibilityEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;service&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="JsonServicesSample.StringHandler"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;endpoint&lt;/span&gt; &lt;span class="attr"&gt;address&lt;/span&gt;&lt;span class="kwrd"&gt;=""&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;behaviorConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;="StringHandlerBehavior"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;binding&lt;/span&gt;&lt;span class="kwrd"&gt;="webHttpBinding"&lt;/span&gt;&lt;br /&gt;                  &lt;span class="attr"&gt;contract&lt;/span&gt;&lt;span class="kwrd"&gt;="JsonServicesSample.StringHandler"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.serviceModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Since the service will be deployed in a IIS environment, the StringHandler.svc is created.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span&gt;&amp;lt;%@ServiceHost&lt;br /&gt;   Service="JsonServicesSample.StringHandler" %&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The server configuration tasks are done, now the service reference needs to be included in the page's Script Manager&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="ScriptManager1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ServiceReference&lt;/span&gt;&lt;br /&gt;          &lt;span class="attr"&gt;Path&lt;/span&gt;&lt;span class="kwrd"&gt;="~/StringHandler.svc"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;And everything is ready to start using the service from client side script code.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; ToUpper(name)&lt;br /&gt;{&lt;br /&gt;    JsonServices.Contract.Sample.StringHandler&lt;br /&gt;    .ToUpper(name, OnSuccedeed, OnFailed);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; OnSuccedeed(res)&lt;br /&gt;{&lt;br /&gt;    alert(res);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; OnFailed(error)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;// Alert user to the error.&lt;/span&gt;&lt;br /&gt;    alert(error.get_message());&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;You may have already noticed that instead of using the service .NET class namespace (JsonServicesSample) as we did in the Web Services sample, this proxy uses JsonService.Contract.Sample, but what the ** is that? Well if you go back to the StringHandler implementation you'll notice that the ServiceContract defines a namespace...&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;[ServiceContract&lt;br /&gt;(Namespace=&lt;span class="str"&gt;"JsonServices.Contract.Sample"&lt;/span&gt;)]&lt;/pre&gt;&lt;br /&gt;So the bottom line is that &lt;strong&gt;WCF client-side proxys use the contract namespace in contrast with Ajax Web services which use the .NET class namespace instead.&lt;/strong&gt;.&lt;br /&gt;And that's it, our WCF service and client are ready. Before finishing though, it's worth mentioning the &lt;strong&gt;WebScriptServiceHostFactory&lt;/strong&gt; Service Host Factory and how it can help us to remove configuration from Json WCF services.&lt;br /&gt;Comparing to the Web service solution, in WCF sample an additional step was taken in order to define the service and endpoint configuration. If you want to keep it simple and skip that step you can do it using the WebScriptServiceHostFactory Service Host factory. This factory creates ServiceHosts with the default services, endpoints and behaviours suitable for this Json web environment so explicit configuration is no longer needeed&lt;br /&gt;In order to achieve it, if we look at the sample then, the service factory is declared in the .svc file...&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span&gt;&amp;lt;%@ServiceHost&lt;br /&gt;   Service="JsonServicesSample.StringHandler"&lt;br /&gt;   Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"%&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;...so the WCF configuration can be now wiped out from the web.config file.&lt;br /&gt;&lt;br /&gt;That's all folks! I hope that if you weren't familiar with this subject this rather long post has given you an idea of what it takes to implement basic Json services in ASP.NET.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fjson-services-in-aspnet-ajax.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fjson-services-in-aspnet-ajax.html&amp;&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-1800364193211564221?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/1800364193211564221/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/05/json-services-in-aspnet-ajax.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/1800364193211564221?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/1800364193211564221?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/VMttZdTJobw/json-services-in-aspnet-ajax.html" title="JSON services in ASP.NET Ajax" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/05/json-services-in-aspnet-ajax.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIARnozfip7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-6339035034018055280</id><published>2008-05-03T15:49:00.013+02:00</published><updated>2008-12-09T00:05:47.486+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:05:47.486+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="Castle" /><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><title>Dependency Injection in WCF Services Part 2</title><content type="html">In the &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services.html"&gt;first post of these series&lt;/a&gt;, I explained the problems you may run into when applying Dependency Injection in your distributed service layer and some of the available solutions to get them around, mainly focusing WCF services. Let's finish off with the theory and put one of those solutions in practice, shall we? In this post I'll rework the sample that I used in my previous post to show the Service Locator pattern in order to use Dependency Injection instead. As in the project that I'm currently working on we are using Castle, I'll use WCF Castle facility to do the service injection.&lt;br /&gt;&lt;br /&gt;Let's take then my Service Locator sample&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerService:ICustomerService&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer GetCustomer(&lt;span class="kwrd"&gt;long&lt;/span&gt; id)&lt;br /&gt;        {&lt;br /&gt;            ICustomerDataAccess da;&lt;br /&gt;            da = Global.Container.Resolve&amp;lt;ICustomerDataAccess&amp;gt;();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; da.GetCustomer(id);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;and rework it to use Dependency Injection&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerService:ICustomerService&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; properties&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; ICustomerDataAccess customerDataAccess;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ICustomerDataAccess CustomerDataAccess&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; customerDataAccess; }&lt;br /&gt;            set { customerDataAccess = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer GetCustomer(&lt;span class="kwrd"&gt;long&lt;/span&gt; id)&lt;br /&gt;        {&lt;br /&gt;        &lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; CustomerDataAccess.GetCustomer(id);&lt;br /&gt;        }&lt;br /&gt;    &lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;You can notice that with those changes our service class is no longer dependant on the DI container for resolving the CustomerDataAccess implementation like it is in the Service Locator example. Instead, the Data access dependency is a property that can be injected by an external agent, which can be whatever DI container we want to use or even a simple factory... Let's focus on this sample though!&lt;br /&gt;&lt;br /&gt;The next step is to create a Castle configuration file called "Objects.xml" where both service and data access objects are defined.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerService"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.ICustomerService, DISample.Service"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.Service.CustomerService, DISample.Service"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="CustomerDataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.ICustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;br /&gt;               &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="DISample.DataAccess.CustomerDataAccess, DISample.DataAccess"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;As you can see there is no need to connect the DataAccess dependency to the Service object in the configuration file; Castle automatically wires it up.&lt;br /&gt;&lt;br /&gt;Now that the Service code is ready for injection and the objects are defined in a configuration file, it's time to use the WCF facility to do the actual service injection.&lt;br /&gt;In order to install the dependency injection behavior, Castle facility uses a a custom WCF ServiceHost. Then, for a non-IIS 6.0 environment and asuming that the service and the endpoint configuration are located in an external configuration file, our WCF host creation would look something like this.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;WindsorContainer container = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer(&lt;span class="str"&gt;"Objects.xml"&lt;/span&gt;);&lt;br /&gt;Uri uri = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(&lt;span class="str"&gt;"net.tcp://localhost/DISample"&lt;/span&gt;);&lt;br /&gt;WindsorServiceHost host = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorServiceHost(container.Kernel, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(CustomerService), uri);&lt;br /&gt;host.Open();&lt;/pre&gt;&lt;br /&gt;We instantiate the Windsor container with our object configuration file so as to be used by the custom service host... and that's all for non-IIS6.0 hosts!&lt;br /&gt;&lt;br /&gt;As you may already know, ServiceHost instatiatation model for WCF services host under II6.0 is different: We don't explictly create the ServiceHost; instead ServiceHosts are created by a ServiceHostFactory on each HTTP request.&lt;br /&gt;WCF castle facility provides a custom ServiceHostFactory that can be specified for its use in IIS6 .svc service files. Let's change the default CustomerService.svc accordingly.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span&gt;&amp;lt;%@ ServiceHost Service="CustomerService"&lt;br /&gt;Factory="Castle.Facilities.WcfIntegration.WindsorServiceHostFactory, Castle.Facilities.WcfIntegration" %&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Where the value of attribute Service must match either the id of our service in Castle configuration file or the service type itself.&lt;br /&gt;Are we missing anything? We haven't created the Windsor Container yet, have we?. Like I said before in II6.0 environments ServiceHosts are created by http request, but would it be wise to apply the same approach for creating the WindsorContainer? I don't think so! Don't panic though, WCF facility has already covered that. Since we are in a web environment, we can use the Global.asax Application_Start event to create our Windsor Container and then register it through an available method in the custom ServiceHostFactory.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Global : System.Web.HttpApplication&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Application_Start(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            WindsorContainer container = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer(&lt;span class="str"&gt;"Objects.xml"&lt;/span&gt;);&lt;br /&gt;            WindsorServiceHostFactory.RegisterContainer(container.Kernel);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We are done! What's next then? One of the things that I pointed out &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services.html"&gt;in the first post of this series&lt;/a&gt; is that no AOP features can be applied upon objects that are not handled by the DI container... That's no longer a problem for us!&lt;br /&gt;In the &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services_17.html"&gt;next post of these series&lt;/a&gt; I'll show how we can use castle interceptors to apply cross cutting concerns upon service objects.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fdependency-injection-in-wcf-services_03.html"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fdependency-injection-in-wcf-services_03.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-6339035034018055280?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/6339035034018055280/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/05/dependency-injection-in-wcf-services_03.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/6339035034018055280?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/6339035034018055280?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/cH4fnV0r5_c/dependency-injection-in-wcf-services_03.html" title="Dependency Injection in WCF Services Part 2" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/05/dependency-injection-in-wcf-services_03.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMHRX46fCp7ImA9WxRbF0o.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-5114530709625080319</id><published>2008-05-01T18:50:00.036+02:00</published><updated>2008-12-09T00:03:54.014+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T00:03:54.014+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="WebServices" /><category scheme="http://www.blogger.com/atom/ns#" term="Castle" /><category scheme="http://www.blogger.com/atom/ns#" term="Spring.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><title>Dependency Injection in WCF Services</title><content type="html">To use &lt;a href="http://www.martinfowler.com/articles/injection.html#FormsOfDependencyInjection"&gt;Dependency Injection&lt;/a&gt; in a distributed service layer is not a trivial task. Either if you use Web Services or WCF, your services are created by the .NET engine, so somehow you need to find a way to inject your Dependency Injection Container in there.&lt;br /&gt;&lt;br /&gt;You might as well let the engine create your service and then use the &lt;a href="http://www.martinfowler.com/articles/injection.html#UsingAServiceLocator"&gt;Service Locator pattern&lt;/a&gt; to hook up the underlying layer.&lt;br /&gt;In the following code snippet we use &lt;a href="http://www.castleproject.org/"&gt;Castle container&lt;/a&gt; as a Service Locator to retrieve the Data Access Layer instance that is used from our WCF service.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomerService:ICustomerService&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; ICustomerService Members&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Customer GetCustomer(&lt;span class="kwrd"&gt;long&lt;/span&gt; id)&lt;br /&gt;        {&lt;br /&gt;            ICustomerDataAccess da;&lt;br /&gt;            da = Global.Container.Resolve&amp;lt;ICustomerDataAccess&amp;gt;();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; da.GetCustomer(id);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;In the above example, you'll notice that apart from using &lt;a href="http://www.martinfowler.com/articles/injection.html#ServiceLocatorVsDependencyInjection"&gt;a slightly different pattern&lt;/a&gt; for creating the Data Access object, the service instantiation is not handled by our DI container and this has some bad implications. Some DI containers, such as Castle or Spring.NET, offer &lt;a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming"&gt;AOP&lt;/a&gt; features but those features can only be applied upon objects instantiated by the container. So the bottom line is that in this scenario we can't use those AOP frameworks upon our service objects.&lt;br /&gt;&lt;br /&gt;So for some scenarios Service Locator pattern could be just alright, but what if we still want to go for a pure Dependency Injection pattern in our service layer? How can we get around the service creation problem?&lt;br /&gt;&lt;br /&gt;If you are using Web Services I'm afraid you don't have many options. Comparing to WCF, Web services is not a very configurable technology and the only way to intercept requests is to replace the ASP.NET default HttpHandler with a custom one, which handles the requests/responses and the service object creation. Good news are that if you are using &lt;a href="http://www.springframework.net/"&gt;Spring.NET&lt;/a&gt;, you don't need to create the handler yourself; there is a &lt;a href="http://www.springframework.net/doc-latest/reference/html/webservices.html"&gt;custom HttpHandler implementation&lt;/a&gt; in the framework that you can use for that purpose.&lt;br /&gt;&lt;br /&gt;If you are using WCF in your service layer, congratulations :) WCF is a highly configurable technology and in fact it provides AOP features through the injection of &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163302.aspx"&gt;custom behaviors&lt;/a&gt;. Using this extensibility &lt;a href="http://orand.blogspot.com/"&gt;Oran&lt;/a&gt; gives us the solution to our problem &lt;a href="http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html"&gt;here&lt;/a&gt;. As you can read in that post, for creating new service instances WCF uses a factory, which implements IInstanceProvider ... Great news are that we can create a custom behavior that replaces the default IInstanceProvider factory implementation with our own implementation, and in there we can hook up our DI Container.&lt;br /&gt;To cut a long story short, Oran creates an IInstanceProvider implementation that uses Spring.NET container for service objects creation.&lt;br /&gt;&lt;br /&gt;If you are not using Spring.NET, don't panic :) there are also implementations available &lt;a href="http://www.ayende.com/Blog/archive/2007/06/12/WCF-Windsor-Integration.aspx"&gt;for Castle&lt;/a&gt; (created by &lt;a href="http://www.ayende.com/"&gt;Ayende&lt;/a&gt;) and &lt;a href="http://weblogs.asp.net/cibrax/archive/2007/12/13/wcf-dependency-injection-behavior.aspx"&gt;for ObjectBuilder&lt;/a&gt; (created by &lt;a href="http://weblogs.asp.net/cibrax/default.aspx"&gt;Pablo M. Cibraro&lt;/a&gt;) that follow similar approaches than Oran's. Even if you are using Spring.NET, you might as well use &lt;a href="http://plainoldstan.blogspot.com/2008/03/source-code-for-amendments-to-oran.html"&gt;Stan's ammendments&lt;/a&gt; to Oran's solution.&lt;br /&gt;&lt;br /&gt;To sum up, in this post we have explored some different options to implement Dependency Injection in our Service Layer depending on the distributed technology (WebServices and WCF) and on the DI container (Spring.NET, Castle..) used.&lt;br /&gt;&lt;br /&gt;In the &lt;a href="http://javicrespotech.blogspot.com/2008/05/dependency-injection-in-wcf-services_03.html"&gt;next post of these series&lt;/a&gt;, I'll put these concepts in practice using the WCF Dependency Injection Castle facility.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fdependency-injection-in-wcf-services.html"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fjavicrespotech.blogspot.com%2f2008%2f05%2fdependency-injection-in-wcf-services.html&amp;bgcolor=3E700F&amp;cbgcolor=CAF99B" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-5114530709625080319?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/5114530709625080319/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/05/dependency-injection-in-wcf-services.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/5114530709625080319?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/5114530709625080319?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/hDSNCod-JV8/dependency-injection-in-wcf-services.html" title="Dependency Injection in WCF Services" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/05/dependency-injection-in-wcf-services.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEACSH04eyp7ImA9WxdTFEw.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-9177220554612219265</id><published>2008-04-29T19:56:00.001+02:00</published><updated>2008-05-10T12:52:49.333+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-10T12:52:49.333+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ADO.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Certifications" /><category scheme="http://www.blogger.com/atom/ns#" term="LINQ" /><title>ADO.NET 3.5 Certification exam</title><content type="html">A few days ago I sat for the beta exam &lt;a href="http://www.microsoft.com/learning/exams/70-561.mspx"&gt;70-561 .NET Framework 3.5 ADO.NET&lt;/a&gt;. This is the second exam that I've taken for the new .NET 3.5 certifications generation; at the end of last year I took &lt;a href="http://www.microsoft.com/learning/exams/70-503.mspx"&gt;70-503 WCF's exam&lt;/a&gt; and I recently got the &lt;a href="http://blogs.msdn.com/gerryo/archive/2008/04/14/exams-live-today.aspx"&gt;results&lt;/a&gt; with a happy end for me :)&lt;br /&gt;&lt;br /&gt;In 70-561 exam besides traditional topics such as ADO.NET connected data(Commands, DataReaders, etc) and ADO.NET disconnected data (DataSets, DataTables, etc), there is plenty of new stuff that you'd better be familiar with if you want to pass! One of those things is LINQ and LINQ to SQL, which I didn't find particularly difficult maybe cause I've had the chance to work with it.&lt;br /&gt;&lt;br /&gt;If you are not familiar with LINQ to SQL, my buddy &lt;a href="http://www.sidarok.com/web/blog/index.php"&gt;Sidar&lt;/a&gt; came up with a great &lt;a href="http://www.sidarok.com/web/blog/content/2008/04/21/a-brief-introduction-to-linq-to-sql.html"&gt;introduction post&lt;/a&gt; and Scott Guthrie has a very nice &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx"&gt;series of posts&lt;/a&gt; that you don't want to miss out.&lt;br /&gt;&lt;br /&gt;Another new topic, (at least for me) was Synchronization services. Maybe it's because I've never used it, but questions about Synchronization Services were by far the most difficult for me! You can find &lt;a href="http://www.syncguru.com/Projects.aspx"&gt;here&lt;/a&gt; a bunch of demos for the Synchronization framework that you might find useful.&lt;br /&gt;&lt;br /&gt;The last but not the least is the Entity Framework which is still in beta... That's one of the disadvantages of taking beta exams, you are sometimes supposed to have knowledge and experience in technologies that haven't been available long enough... I won't complain though, beta exams do have some advantages (Did I mention that they are free?:)) You can find some code samples for EF Beta 3 version in &lt;a href="http://www.codeplex.com/adonetsamples/"&gt;CodePlex&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The beta period for this exam and ASP.NET exam have been extended until the 5th of May, so if you haven't sat for it yet and you want to take it, hurry up and check &lt;a href="http://blogs.msdn.com/gerryo/archive/2008/04/02/asp-net-and-ado-net-beta-exams-extended.aspx"&gt;Gerry's certification blog&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-9177220554612219265?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/9177220554612219265/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/04/adonet-35-certification-exam.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/9177220554612219265?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/9177220554612219265?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/J3OsYhKUxuI/adonet-35-certification-exam.html" title="ADO.NET 3.5 Certification exam" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/04/adonet-35-certification-exam.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUGR3wzeip7ImA9WxZaGUo.&quot;"><id>tag:blogger.com,1999:blog-5608490812663757705.post-8103364054951074410</id><published>2008-04-28T19:37:00.000+02:00</published><updated>2008-05-05T10:47:06.282+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-05T10:47:06.282+02:00</app:edited><title>Welcome to Javi's tech blog!</title><content type="html">So here I am, I've finally decided to have my own technical blog! I've always been very reluctant to start blogging as I’m the kind of tech guy that would rather write code than explain things in a piece of paper or write documentation in general (I'm even very fond of tools like &lt;a href="http://www.roland-weigelt.de/ghostdoc/"&gt;GhostDoc&lt;/a&gt; that help you to make the task of commenting code a bit less tough... too lazy I am I must admit, too bad...)&lt;br /&gt;&lt;br /&gt;I hope then that having a blog will help me to look at the task of writing documentation and posts in a different way, more as fun and less as a burden, and besides it’ll force me to keep up to date to the latest technologies, so overall it does sound like a good idea, doesn’t it? And, on top of that, if anybody finds my posts useful, that'd be great!!&lt;br /&gt;&lt;br /&gt;So as long as I can find some spare time and I have something to say, I’ll be blogging about .NET and related technologies such as ASP.NET, LINQ, WCF, Ajax…&lt;br /&gt;&lt;br /&gt;I hope that you'll be around to check wether this experiment works out or not!&lt;br /&gt;&lt;br /&gt;Javi&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5608490812663757705-8103364054951074410?l=javiercrespoalvez.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://javiercrespoalvez.com/feeds/8103364054951074410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javiercrespoalvez.com/2008/04/welcome-to-javis-tech-blog.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8103364054951074410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5608490812663757705/posts/default/8103364054951074410?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JavisTechnicalBlog/~3/YapnK2XdsNs/welcome-to-javis-tech-blog.html" title="Welcome to Javi's tech blog!" /><author><name>Javi</name><uri>http://www.blogger.com/profile/11872722615399930636</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17090524348135044013" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://javiercrespoalvez.com/2008/04/welcome-to-javis-tech-blog.html</feedburner:origLink></entry></feed>
