tag:blogger.com,1999:blog-13119433658024608942024-03-13T11:59:04.179-04:00Code::Reflected// TODO: Insert posts below...Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-1311943365802460894.post-32217182770574514142013-01-07T07:21:00.000-05:002013-01-07T07:34:14.973-05:00Null MessageBodyMember for WCF Stream ResponseIf you are using a WCF <code>MessageContract</code> that contains a <code>MessageBodyMember</code> of type <code>Stream</code>, as shown below, the <code>Stream</code> can <u>never</u> be <code>null</code>.<br />
<br />
<pre class="prettyprint lang-csharp">[MessageContract(WrapperNamespace = "Learnsomething.com/Internal/DataContracts/Responses/Certificates")]
public class CreateCertificateResponse : BaseResponseMessageContract, IDisposable
{
[MessageHeader(Namespace = "Learnsomething.com/Internal/DataContracts/Responses/Certificates")]
public long FileLength { get; set; }
[MessageBodyMember(Order = 1, Namespace = "Learnsomething.com/Internal/DataContracts/Responses/Certificates")]
public Stream CertificatePDF { get; set; }
public void Dispose()
{
if (this.CertificatePDF != null)
{
this.CertificatePDF.Dispose();
this.CertificatePDF = null;
}
}
}
</pre>
<br />
If it is <code>null</code> when the response is sent back, then the connection will be closed improperly with a <i>The socket connection was aborted</i> error message.
<br />
<br />
If you must support a <code>null</code> <code>Stream</code> in the response, you can make use of the <code>System.IO.Stream.Null</code> value. That object is internal, called <code>NullStream</code> and inherits from <code>Stream</code>.<br />
<br />
<b>Links</b>
<br />
<br />
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/system.io.stream.null.aspx">System.IO.Stream.Null</a></li>
<li><a href="http://stackoverflow.com/a/7320858/498969">Related Stackoverflow answer</a></li>
</ul>
Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-89503026924009268072012-09-30T16:16:00.002-04:002013-01-07T07:34:39.293-05:00Queue up jQuery requests before it is loaded<div>
If you are loading jQuery just before the closing body tag (<i>if not, stop and <a href="http://developer.yahoo.com/performance/rules.html#js_bottom" target="_blank">read this now</a></i>), you may be wondering how you can use jQuery before it has been loaded on your page above. Maybe it forced you find some crazy script ordering scheme or maybe you just gave up and included it somewhere else in the body or even in the head.</div>
<div>
<br /></div>
<div>
In a CMS world, each widgets could emit javascript that relies on jQuery existing on the page, but since it isn't loaded until just before the closing body tag, we need a way to <i>fake</i> a reference to jQuery and queue up the requests temporarily until jQuery has been loaded.<br />
<br />
I came across <a href="http://www.mrclay.org/2010/11/14/using-jquery-before-its-loaded/" target="_blank">this post</a> that seemed to do exactly what we needed. Before jQuery is loaded, the script will queue the jQuery functions calls. Once loaded, the functions are dequeued and executed. Hooking up the script is simple and only involves adding a few small scripts to your page. </div>
<div>
<br /></div>
<div>
First you have to add an inline script to your head tag. The script will create a fake <code>$</code> reference on the window if jQuery hasn't yet loaded which pushes each function onto an array. It then defines a new function that will be used to execute each function after jQuery eventually loads.</div>
<div>
<br />
<pre class="prettyprint lang-js"><script type="text/javascript">
(function (a) {
if (a.$ || a.jQuery) return;
var b = [];
a.$ = function (c) { b.push(c) };
a.defer$ = function () { while (f = b.shift()) $(f) } }
)(window);
</script>
</pre>
</div>
<div>
<br /></div>
<div>
Next include jQuery just before the closing body tag.</div>
<div>
<pre class="prettyprint lang-js"><script type="text/javascript" src="/scripts/jquery.min.js">
</pre>
</div>
<div>
<br /></div>
<div>
Finally, after the jQuery include, call the defer function that we defined in the header. This will loop through each function that was deferred and execute them now that jQuery has been loaded.</div>
<div>
<br />
<pre class="prettyprint lang-js"><script type="text/javascript">
defer$();
</script>
</pre>
</div>
<div>
<br />
This is a pretty cool trick, and while I can't take credit for it, I wanted to put the information out there for others to learn from.<br />
<br />
<b>Links</b></div>
<div>
<ul>
<li><a href="http://developer.yahoo.com/performance/rules.html#js_bottom" target="_blank">Put your scripts at the bottom</a></li>
<li><a href="http://www.mrclay.org/2010/11/14/using-jquery-before-its-loaded/" target="_blank">Use jQuery before it loads</a></li>
</ul>
</div>
Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-51269827640698225922012-06-14T22:36:00.001-04:002013-01-07T07:35:04.817-05:00Working around RavenDB and Safe-By-DefaultI have seen these questions from time to time.<br />
<blockquote class="tr_bq">
<i>"How can I get all of the documents in RavenDB?"</i></blockquote>
<blockquote class="tr_bq">
<i>"How can I force RavenDB to return more documents that the "safe-by-default" limits?"</i></blockquote>
The questions above usually stem from someone needing to work around the "safe-by-default" protection due to some sort of special circumstance. So if you find yourself needing these techniques more often than not, then <u>you are doing it wrong</u>.<br />
<br />
You can change the RavenDB configuration by increasing the default <b>PageSize</b>, but that is a global change. <b><i>Instead</i></b> you need to do two things.<br />
<ol>
<li>Ensure that you start a new <code>DocumentSession</code> when you reach the
<code>MaxNumberOfRequestsPerSession</code> limit.</li>
<li>Make sure you page the query with respect to the RavenDB <code>PageSize</code> (which is 1024 by default).</li>
</ol>
The RavenDB paging mechanism <b>will not</b> override the configured maximum number of items allowed per page. So if you try to <code>Take()</code> more than the configured limit, you will not get an error. Instead RavenDB's <i>safe-by-default</i> kicks in and will impose the configured page size on your results.<br />
<br />
Below is an example that gets all document id values that match the predicate.<br />
<br />
<pre class="prettyprint lang-csharp">IDocumentSession session = null;
try
{
session = MvcApplication.DocumentStore.OpenSession();
List<string> ravenPageIds = null;
const int RAVEN_MAX_PAGE_SIZE = 1024;
int currentPageNumber = 0;
do
{
List<string> tempRavenPageIds = (from p in session.Query<Page>()
where p.IsActive == true
select p.Id)
.Skip(currentPageNumber++ * RAVEN_MAX_PAGE_SIZE)
.Take(RAVEN_MAX_PAGE_SIZE).ToList();
ravenPageIds.AddRange(tempRavenPageIds);
if (session.Advanced.NumberOfRequests >= session.Advanced.MaxNumberOfRequestsPerSession)
{
session.Dispose();
session = MvcApplication.DocumentStore.OpenSession();
}
} while (tempRavenPageIds.Count == RAVEN_MAX_PAGE_SIZE);
}
finally
{
session.Dispose();
}
</pre>
We had code similar to this that needed to run when an MVC Application started (<i>in order to build page routing table</i>). But since then, we were able to refactor the code such that we no longer need to employ this technique. Rather than simply throw it away, perhaps you may find it useful.<br />
<br />
<br />
<b>Links</b><br />
<br />
<ul>
<li><a href="http://ravendb.net/docs/client-api/basic-operations/understanding-session-object">RavenDB - Understanding the session object.</a></li>
<li><a href="https://groups.google.com/group/ravendb/browse_thread/thread/128f7a7eaa3256f7/78c2e59cab3df2da">RavenDB Google Groups discussion on MaxPageSize</a></li>
</ul>
<br />Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-34174966307511477332012-05-24T14:35:00.000-04:002013-01-07T07:35:54.523-05:00MVC3 Razor and Preprocessor Directives DeficiencyYou may have used preprocessor directives in ASP.NET Webforms to conditionally include code segments in markup for in the code-behind files. I have used them in master pages and aspx pages to do things like conditionally including Google Analytics or include compressed versus verbose CSS and Javascript.<br />
<br />
Example including Google Analytics when DEBUG is not defined.<br />
<pre class="prettyprint lang-csharp"><% #if !DEBUG %>
<script type="text/javascript" src="/scripts/ga.min.js"></script>
<% #endif %></pre>
<br />
Example including verbose CSS versus minified CSS.<br />
<pre class="prettyprint lang-csharp"><% #if DEBUG %>
<link rel="stylesheet" href="/Styles/Default.css" type="text/css" />
<% #else %>
<link rel="stylesheet" href="/Styles/Default.min.css" type="text/css" />
<% #endif %></pre>
<br />
If you are like me, you may have tried to use this technique in MVC3 Razor. But what you may not know is that MVC Razor views are always compiled in DEBUG mode! That's right, it does not respect the debug attribute on your compilation web.config element! This is a huge issue, and frankly I am surprised that this has not yet been fixed.<br />
<br />
In trying to find answers, I found <a href="http://forums.asp.net/post/4207437.aspx">this response</a> on <a href="http://forums.asp.net/t/1625220.aspx/">this thread</a> which confirms the issue.<br />
<br />
There is hope though! We have a few ways that we can conditionally include code in our Razor views.<br />
<br />
<h3>
Use IsDebuggingEnabled</h3>
Instead of using preprocessor directives in Razor, you can instead use the following property to test if the web.config compilation element's debug property (Reference here: <a href="http://stackoverflow.com/a/4509854/498969">Stack Overflow</a>).<br />
<pre class="prettyprint lang-csharp">HttpContext.Current.IsDebuggingEnabled</pre>
<br />
That property will check your compilation element's debug property in web.config.<br />
<pre class="prettyprint lang-xml"><system.web><compilation debug="true">...</compilation></system.web>
</pre>
<br />
<h3>
Create a Static Extension Method that uses preprocessor directives</h3>
Shawn on Stack Overflow <a href="http://stackoverflow.com/a/7135343/498969">posted an example</a> of an extension method that can be used in conjunction with preprocessor directives.<br />
<pre class="prettyprint lang-csharp"> public static bool IsDebug(this HtmlHelper htmlHelper)
{
#if DEBUG
return true;
#else
return false;
#endif
}
</pre>
<br />
Then in your view, just check IsDebug().<br />
<br />
<br />
IMHO, this issue should be addressed in MVC4. There is no reason for the code bloat that Razor causes by not respecting the DEBUG compilation flag. If anyone can find the Microsoft connect issue, please comment and I'll add in my 2 cents!<br />
<br />
<b>Links</b><br />
<br />
<ul>
<li><a href="http://forums.asp.net/t/1625220.aspx">MSDN Razor Compilation</a></li>
<li><a href="http://stackoverflow.com/a/4509854/498969">Stack Overflow IsDebuggingEnabled</a></li>
<li><a href="http://stackoverflow.com/a/7135343/498969">Stack Overflow IsDebug extension method</a></li>
</ul>
Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com1tag:blogger.com,1999:blog-1311943365802460894.post-38696911958578499242011-10-28T10:34:00.001-04:002011-10-28T10:35:05.001-04:00Classes, Structs and LLBLGen ProI just found an interesting bug that has trickled into some of our code.<br />
<br />
<b>Can you identify what is wrong with the following code (<i>don’t cheat by reading below</i>):</b><br />
<pre class="prettyprint lang-csharp">Guid? enrollmentId = (from e in metaData.Enrollment
where e.LearnerId == learnerId
select e.Id).FirstOrDefault();
</pre><br />
The problem comes from the way that <code>FirstOrDefault()</code> operates. In LLBLGen's case, that method will either take the first value, or it will set the default value if it does not find a match. This is where it is important to know what you are selecting. In this case, the query is selecting the <code>e.Id</code>, which is a <code>Guid</code>. A <span class="Apple-style-span" style="font-family: monospace;">Guid</span> can <u>never be null</u> because it is a <i>struct</i> and it is not a <i>class</i>.<br />
<blockquote><i>Other things that are structs include:</i> bool, int, short, long, byte, DateTime, KeyValuePair<u,v>, etc...</u,v></blockquote>If you are selecting a value that is a <i>class</i>, the default value will be <b>NULL</b> because classes are reference types. <br />
If you are selecting a value that is a struct, the default value will <b>never be NULL</b> because structs are <a href="http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx">value types</a>.<br />
<blockquote><i>Side Note</i>: The default value for a struct can be determined generically using the following (<i>Where T is a type of struct)</i>:<br />
<pre class="prettyprint lang-csharp">T defaultValueForType = default(T);</pre></blockquote><b>So how do we select a struct using FirstOrDefault()?</b><br />
You can work around this by selecting a class instead. The best way to do it is to use an Anonymous Type as shown below.<br />
<pre class="prettyprint lang-csharp">var enrollmentId = (from e in metaData.Enrollment
where e.LearnerId == learnerId
select new { e.Id }).FirstOrDefault();
</pre><br />
Anonymous Types are classes, therefore they can be null. By using an anonymous type in our query, the <code>enrollmentId</code> variable will be NULL if there are no records found.<br />
<br />
<span class="Apple-style-span" style="color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; line-height: 18px;"><b>Links</b></span><br />
<ul><li><a href="http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx">MSDN Value Types Reference</a></li>
</ul>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-57590504910502417202011-05-01T14:58:00.004-04:002011-05-01T15:21:44.063-04:00.NET 4 Concurrent Dictionary GotchasWhile the .NET ConcurrentDictionary<T, V> is thread-safe, not all of its methods are atomic. Microsoft points out (<a href="http://msdn.microsoft.com/en-us/library/dd997369.aspx">http://msdn.microsoft.com/en-us/library/dd997369.aspx</a>) that the <b>GetOrAdd</b> and <b>AddOrUpdate</b> methods that take in a delegate invoke the delegate outside of the locking mechanism used by the dictionary.<br />
<br />
Because the locking is not employed when invoking the delegate, it could get executed more than once. I wrote some sample code and posted it onto a new <a href="http://www.stackoverflow.com/">StackOverflow</a> community called <a href="http://codereview.stackexchange.com/">CodeReview</a> to get some feedback from the community on an approach to use the delegate overloads while maintaining atomicity. I found that by writing an extension method for the delegate methods I could use the <b>.NET Lazy<T> </b>class as a wrapper for the value in the dictionary. Because the Lazy<T> class is only evaluated once, the new methods are atomic.<br />
<br />
Pinned below is the CodeReview post.<br />
<div id="stacktack-2025" class="makePretty"></div>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-46003285855467212992011-01-04T00:06:00.000-05:002011-01-04T00:06:54.851-05:00.NET 4 Concurrent Dictionary Collection<div>In ASP.NET we use a few static generic dictionaries that store data which needs to be accessed very quickly. Generic dictionaries are not thread-safe when adding items so we had to provide locks around all access to the collection.</div><br />
<b>Example using locks to add thread-safety when manipulating a generic dictionary.</b><br />
<pre class="prettyprint lang-csharp">private static readonly object cachedAnonymousIdentitiesLock = new object();
private static readonly Dictionary<Guid, Identity> cachedAnonymousIdentities =
new Dictionary<Guid, Identity>();
private Identity GetAnonymousIdentity(Guid orgId)
{
Identity id = null;
lock (cachedAnonymousIdentitiesLock)
{
if (cachedAnonymousIdentities.ContainsKey(orgId))
id = cachedAnonymousIdentities[orgId];
else
{
id = new Identity(orgId);
cachedAnonymousIdentities.Add(orgId, id);
}
}
return id;
}
</pre><br />
The code above uses a mutual exclusion lock to provide thread-safe access to the generic dictionary which contains an immutable Identity object. While this code works fine, it does take a performance hit because of the blocking mutual exclusion lock. If a thread becomes blocked because of the lock, extra overhead is encountered because a context switch in the OS will occur. We really only need to maintain a lock for a very small amount of time while a new item is added to the collection (and truthfully a spin lock would be more efficient here).<br />
<br />
Now in case you haven't heard, there is a new namespace in .NET 4 for concurrent collections. When I found out about this I immediately got the refactor itch. The thread-safe collections are discussed on <a href="http://msdn.microsoft.com/en-us/library/dd997305.aspx">MSDN</a>. Looking around I found the <a href="http://msdn.microsoft.com/en-us/library/dd287191.aspx">System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue></a> class. This class uses a spin lock instead of a blocking lock for thread-safe access. Additionally the class provides a few friendly methods that make adding a new item to the dictionary easier. The <a href="http://msdn.microsoft.com/en-us/library/ee378676.aspx">GetOrAdd</a> method is a welcomed method that allows you to quickly either get the item or add it to the dictionary. Below is the same code above refactored using the ConcurrentDictionary.<br />
<br />
<pre class="prettyprint lang-csharp">private static readonly ConcurrentDictionary<Guid, Identity> cachedAnonymousIdentities =
new ConcurrentDictionary<Guid, Identity>();
private Identity GetAnonymousIdentity(Guid orgId)
{
return cachedAnonymousIdentities.GetOrAdd(orgId, key => new Identity(orgId));
}
</pre><div>The code is easy to follow and the locking is done automatically! I ran a quick unit test to double check the efficiency of the ConcurrentDictionary over our previous blocking method. The results show that in our scenario we do achieve a performance boost. Running the example below on a multi-core machine results in the blocking example executing in about 450 milliseconds while the concurrent example executes in about 350 milliseconds.</div><br />
<pre class="prettyprint lang-csharp">private readonly static ConcurrentDictionary<Guid, string> myThreadsafeObjects = new ConcurrentDictionary<Guid, string>();
private readonly static Dictionary<Guid, string> myObjects = new Dictionary<Guid, string>();
private readonly static object lockObj = new object();
[TestMethod]
public void LockingTest()
{
int iterations = 1000000;
string value = "hello world";
int keyCount = 10000;
List<Guid> keys = new List<Guid>(keyCount);
for (int i = 0; i < keyCount; i++)
keys.Add(Guid.NewGuid());
Stopwatch lockSw = new Stopwatch();
lockSw.Start();
Thread t1 = new Thread(() =>
{
for (int i = 0; i < iterations; i++)
{
lock (lockObj)
{
if (!myObjects.ContainsKey(keys[i % keyCount]))
myObjects.Add(keys[i % keyCount], value);
string itemValue = myObjects[keys[i % keyCount]];
}
}
});
t1.Start();
for (int i = 0; i < iterations; i++)
{
lock (lockObj)
{
if (!myObjects.ContainsKey(keys[i % keyCount]))
myObjects.Add(keys[i % keyCount], value);
string itemValue = myObjects[keys[i % keyCount]];
}
}
t1.Join();
lockSw.Stop();
Trace.WriteLine(string.Format("Blocking Dictionary lock test: {0} milliseconds", lockSw.ElapsedMilliseconds));
Stopwatch concurrentSw = new Stopwatch();
concurrentSw.Start();
Thread t2 = new Thread(() =>
{
for (int i = 0; i < iterations; i++)
{
lock (lockObj)
{
string itemValue = myThreadsafeObjects.GetOrAdd(keys[i % keyCount], value);
}
}
});
t2.Start();
for (int i = 0; i < iterations; i++)
{
lock (lockObj)
{
string itemValue = myThreadsafeObjects.GetOrAdd(keys[i % keyCount], value);
}
}
t2.Join();
concurrentSw.Stop();
Trace.WriteLine(string.Format("Concurrent Dictionary lock test: {0} milliseconds", concurrentSw.ElapsedMilliseconds));
}
</pre><br />
<div>I'll take the simpler code and the performance gain. Great job MS on this new .NET class!<br />
<br />
In an upcoming post I'll look into the use of the new <a href="http://msdn.microsoft.com/en-us/library/dd267312.aspx">BlockingCollection</a> class in the Concurrent namespace. The class implements a new <a href="http://www.albahari.com/threading/part2.aspx">Producer-Consumer</a> interface which is a pattern we reply upon in a few scenarios and where we have implemented the best practice ourselves. I am hoping this new collection will again simplify our code while improving efficiency.<br />
<br />
<b>Links</b><br />
<br />
<ul><li><a href="http://channel9.msdn.com/Blogs/philpenn/Concurrent-Programming-with-NET4-Collections">Channel9 into to Concurrent Collection namespace</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx">System.Collections.Concurrent namespace (MSDN)</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/dd997369.aspx">How to Add Items to ConcurrentDictionary (MSDN)</a></li>
<li><a href="http://www.albahari.com/threading/">Joseph Albahari (C# in a Nutshell - Threading in C#)</a></li>
</ul></div>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-8369263004113343582010-12-05T22:03:00.000-05:002010-12-05T22:03:07.682-05:00WCF Services Assisting ASP.NET AjaxWe love the <a href="http://telerik.com/">Telerik ASP.NET Ajax Control</a> set and often rely on it for our Ajax communication in ASP.NET. But sometimes the need for efficiency out weights the ease and maintenance of the plug and play solutions.<br />
<br />
We needed a way to eliminate the page request that happens when interacting with one of our ajaxified controls. UpdatePanels and Telerik's AjaxManager still require the page to go through its entire lifecycle so that a portion of the page can be sent back to the browser. We ventured down a few paths that would allow us to use a usercontrol without loading the hosting page, but those solutions were a hack job at best. <br />
<br />
It turns out that using <b>WCF Services</b> within ASP.NET is quite an elegant solution when having to roll your own AJAX solution. With the proper configuration, the services can run along the ASP.NET pipeline giving you access to authentication and authorization events and the user's session. The services can even handle writing your response to JSON.<br />
<br />
Add a WCF Service to your ASP.NET Web Application. Then double check your web.config to make sure that it has the <b>enableWebScript</b> attribute declared and the <b>aspNetCompatibilityEnabled</b> is set to <b>true</b>. The enableWebScript and aspNetCompatibilityEnabled attributes make the WCF service able to participate in the ASP.NET pipeline.<br />
<br />
<pre class="prettyprint lang-xml"><system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WcfServices.EndpointBehavior">
<b><enableWebScript /> <!-- required for ASP.NET pipeline integration --></b>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WcfServices.ServiceBehavior">
<b><serviceMetadata httpGetEnabled="true" /></b> <b><!-- required for RESTful services -->
</b> </behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment <b>aspNetCompatibilityEnabled="true"</b>
multipleSiteBindingsEnabled="true" />
<services>
<service name="Demo.WcfServices.NewsFeedService" behaviorConfiguration="WcfServices.ServiceBehavior">
<endpoint behaviorConfiguration="WcfServices.EndpointBehavior"
binding="webHttpBinding" contract="Demo.WcfServices.ServiceContracts.INewsFeedService" />
</service>
</services>
</system.serviceModel>
</pre><br />
You can consume your WCF services by adding a ServiceReference on a page.<br />
<br />
<pre class="prettyprint lang-xml"><asp:ScriptManagerProxy runat="server">
<Services>
<asp:ServiceReference Path="~/WcfServices/NewsFeedService.svc" />
</Services>
</asp:ScriptManagerProxy></pre><br />
By adding the ServiceReference, the page will add a javascript include to a proxy class that contains the service prototypes. It contains the prototypes that you will use when calling the service from javascript. To see the javascript proxy class, navigate to the SVC file URL and add either "/JS" or "/JSDEBUG" to the URL. Examine the output for the javascript function prototypes.<br />
<br />
As you can see below, the javascript WCF call looks clean and is easy to follow. This approach has many advantages and it decouples us from the tedious page lifecycle that is induced through UpdatePanels and Telerik's Ajax framework. <br />
<br />
<pre class="prettyprint lang-javascript">function getLatestNews(lastNewsId) {
Demo.INewsFeedService.GetLatestNews(lastNewsId, callbackSuccess, callbackFailed);
}
function callbackSuccess(result) {
$("#newsFeed").prependTo(result);
}
</pre><br />
In our case we used AJAX to WCF in order to get an updated XHTML fragment. Instead of using a usercontrol for presenting the dataset, we used XSLT to render the XHTML for the control. This makes it easy for the WCF AJAX call to return XHTML fragments that can be replaced on the page at the AJAX callback. So go ahead and trade in your UpdatePanels for WCF Services next time you have the need for a specialized AJAX call.<br />
<br />
<b>Links</b><br />
<br />
<ul><li><a href="http://www.telerik.com/products/aspnet-ajax.aspx">Telerik RadControls for ASP.NET AJAX</a></li>
<li><a href="http://www.codeproject.com/KB/aspnet/wcfinjavascript.aspx">WCF in ASP.NET AJAX for beginners</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/t745kdsh.aspx">ASP.NET Web Services [MSDN]</a></li>
</ul>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-79972369275684979442010-11-10T21:44:00.005-05:002010-11-12T21:06:04.587-05:00Visual Studio 2010: ASP.NET ControlBuilder MakeGeneric WorkaroundWorking with enumerations is very code friendly and we use them often especially when we are referencing a lookup table. The ORM that we use (<a href="http://llblgen.com/">LLBLGen Pro</a>) released its latest version recently and they make it even easier for us to map an enumeration to an entity field. <br />
<br />
Sometimes these lookup tables need to be presented to the end user for whatever reason - be it a drop down, radio button list or a check box list. When working in VS 2008 I stumbled onto <a href="http://weblogs.asp.net/ysolodkyy/archive/2007/10/02/control-builders-amp-asp-net-generic-control-classes.aspx">this blog</a> that outlines a straight forward way to create a <i>generic</i> drop down that exposes the the selected value as the specified generic Enum. Using that approach, we centralized all of the enum parsing that goes on for the gets and sets when working with the selected items. We took that implementation and created a generic dropdown and checkbox list. It worked great in our environment at the time which was Visual Studio 2008.<br />
<br />
Here is the checkbox list control that we were using:<br />
<pre class="prettyprint lang-cs">public class EnumCheckBoxList<T> : EnumCheckBoxList where T : struct
{
public List<T> SelectedEnumValues
{
get
{
List<T> items = new List<T>(base.Items.Count);
foreach (ListItem item in base.Items)
{
if (item.Selected)
items.Add((T)Enum.Parse(typeof(T), item.Value));
}
return items;
}
set
{
base.ClearSelection();
foreach (T item in value)
base.Items.FindByValue(Enum.GetName(typeof(T), item)).Selected = true;
}
}
/// <summary>
/// Only valid for use on bit flagged enumerations
/// </summary>
public T? SelectedFlaggedEnumValues
{
get
{
ulong values = 0;
foreach (ListItem item in base.Items)
{
if (item.Selected)
values = values | Convert.ToUInt64((T)Enum.Parse(typeof(T), item.Value));
}
return values == 0 ? null : (T?)Enum.Parse(typeof(T), values.ToString());
}
set
{
if (value != null)
{
Type enumType = typeof(T);
foreach (Enum e in Enum.GetValues(enumType))
{
ulong singleEnumFromFlagResult = 0;
if ((singleEnumFromFlagResult = (Convert.ToUInt64(e) & Convert.ToUInt64(value.Value))) > 0)
{
Enum singleEnumFromFlag = (Enum)Enum.Parse(enumType, singleEnumFromFlagResult.ToString());
base.Items.FindByValue(Enum.GetName(enumType, singleEnumFromFlag)).Selected = true;
}
}
}
}
}
}
[ControlBuilder(typeof(EnumCheckBoxListControlBuilder))]
public partial class EnumCheckBoxList : CheckBoxList
{
public string EnumTypeName { get; set; }
}
public class EnumCheckBoxListControlBuilder : ControlBuilder
{
public override void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string id,
System.Collections.IDictionary attribs)
{
string enumTypeName = (string)attribs["EnumTypeName"];
Type enumType = Type.GetType(enumTypeName);
if (enumType == null)
throw new Exception(string.Format("Type for enum {0} can not be created", enumTypeName));
Type dropDownType = typeof(EnumCheckBoxList<>).MakeGenericType(enumType);
base.Init(parser, parentBuilder, dropDownType, tagName, id, attribs);
}
}</pre><br />
Today our new development is done primarily in Visual Studio 2010. We needed the same functionality for the generic dropdown and checkbox list for our Nucleus project but upon bringing over our implementation we discovered that the <i>ControlBuilder wasn't updating the .designer file</i> - so our controls weren't being converted to their generic implementations. After a little Googling, <a href="https://connect.microsoft.com/VisualStudio/feedback/details/575898/asp-net-controlbuilder-type-substitution-not-respected-in-vs-designer-file">I found a bug</a> entered in Microsoft Connect that described the issue we are having with VS 2010 and it seems that there isn't any workaround currently available for our situation using the ControlBuilder implementation.<br />
<br />
The generic control was nice because programmers wouldn't have to go back and forth suppling plumbing to parse string values into enumerations and vise versa. We took the same idea and instead created a few extension methods. The extension methods shown below have a get and set defined for a list of enumeration values and also a get and set for enumerations that are decorated with the FlagsAttribute. <br />
<br />
<pre class="prettyprint lang-cs">/// <summary>
/// Get the selected enumeration values in the listbox
/// </summary>
/// <typeparam name="T">The type of enumeration represented in the listbox</typeparam>
/// <param name="list">The listbox</param>
/// <returns>Returns the list of selected enumeration values in the listbox</returns>
public static List<T> GetSelectedEnumValues<T>(this ListControl list) where T : struct
{
List<T> items = new List<T>(list.Items.Count);
foreach (ListItem item in list.Items)
{
if (item.Selected)
items.Add((T)Enum.Parse(typeof(T), item.Value));
}
return items;
}
/// <summary>
/// Select the values in the given list of enums in the listbox.
/// </summary>
/// <typeparam name="T">The type of enumeration represented in the listbox</typeparam>
/// <param name="list">The listbox</param>
/// <param name="valuesToSelect">The enum values to select in the listbox</param>
public static void SetSelectedEnumValues<T>(this ListControl list, List<T> valuesToSelect) where T : struct
{
list.ClearSelection();
foreach (T item in valuesToSelect)
list.Items.FindByValue(Enum.GetName(typeof(T), item)).Selected = true;
}
/// <summary>
/// Get the selected enumeration values in the listbox. This method should be called if the enumeration is decorated with the Flags attribute.
/// </summary>
/// <typeparam name="T">The type of enumeration represented in the listbox. This enumeration must be decorated with the Flags attribute</typeparam>
/// <param name="list">The listbox</param>
/// <returns>Returns the selected enumeration values in the listbox as a flagged enumeration. If no values are selected, null is returned</returns>
public static T? GetSelectedFlaggedEnumValues<T>(this ListControl list) where T : struct
{
ulong values = 0;
foreach (ListItem item in list.Items)
{
if (item.Selected)
values = values | Convert.ToUInt64((T)Enum.Parse(typeof(T), item.Value));
}
return values == 0 ? null : (T?)Enum.Parse(typeof(T), values.ToString());
}
/// <summary>
/// Select the values in the given flag enumeration in the listbox.
/// </summary>
/// <typeparam name="T">The type of enumeration represented in the listbox. This enumeration must be decorated with the Flags attribute</typeparam>
/// <param name="list">The listbox</param>
/// <param name="valuesToSelect">The enum values (represented as Flags) to select in the listbox</param>
public static void SetSelectedFlaggedEnumValues<T>(this ListControl list, T valuesToSelect) where T : struct
{
list.ClearSelection();
Type enumType = typeof(T);
foreach (Enum e in Enum.GetValues(enumType))
{
ulong singleEnumFromFlagResult = 0;
if ((singleEnumFromFlagResult = (Convert.ToUInt64(e) & Convert.ToUInt64(valuesToSelect))) > 0)
{
Enum singleEnumFromFlag = (Enum)Enum.Parse(enumType, singleEnumFromFlagResult.ToString());
list.Items.FindByValue(Enum.GetName(enumType, singleEnumFromFlag)).Selected = true;
}
}
}</pre><br />
Hopefully Microsoft responds to the Connect bug with a fix in an upcoming service pack. In the mean time these extension methods will do the trick.<br />
<br />
<b>Links</b><br />
<ul><li><a href="http://weblogs.asp.net/ysolodkyy/archive/2007/10/02/control-builders-amp-asp-net-generic-control-classes.aspx">ASP.NET ControlBuilders for Generic Controls</a></li>
<li><a href="https://connect.microsoft.com/VisualStudio/feedback/details/575898/asp-net-controlbuilder-type-substitution-not-respected-in-vs-designer-file">Microsoft Connect Bug</a></li>
<li><a href="http://llblgen.com/">LLBLGen Pro</a></li>
</ul>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-27346011928282518692010-11-05T21:09:00.000-04:002010-11-05T21:09:09.870-04:00First Sprint in ReviewWow it is hard to believe that it has been two weeks and we have finished our first Sprint. Here is how it came out.<br />
<br />
<b>Committed Tasks</b><br />
We completed all but a couple of the tasks we committed in the Sprint. We under estimated the few learning curves that were introduced by our new environment which caused delays early in the Sprint. <br />
<br />
<b>Review (Demo)</b><br />
Everyone demonstrated the features that they worked on during the Sprint. We all knew what to expect because we were all involved in the planning process. <br />
<br />
<b>Retrospective</b><br />
We noticed a few things that we would change in the next Sprint.<br />
<br />
<ol><li>Use the <i>Work Remaining</i> field on the TFS Tasks to help us better gauge progress and future planning.</li>
<li>When UI elements are "<i>done</i>", gather the team for a quick demo.</li>
<ul><li>We want to collect input early to provide a better polished product at the end of the Sprint.</li>
</ul></ol><div><br />
</div><div>The formal structure and Daily Scrum is welcomed by the team. If you are not already using an agile process like Scrum, give it a try - you will be surprised with the results.</div>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com0tag:blogger.com,1999:blog-1311943365802460894.post-35109405955841210812010-10-25T20:46:00.000-04:002010-10-25T20:46:54.229-04:00New Project - Welcome ScrumBefore today, we were working in an informal agile process with fairly short development cycles. We work as a team but often developers would be unaware of new features that others were working on. A big problem with this is that it makes it difficult for another team member to pick up where someone left off.<div><br />
</div><div>Enter our new project, code name <i>Nucleus</i>. Dave and I have been planning for a few months the vision and features of the project and we formally kicked it off today - Hooray! We were introduced to a new project process called <a href="http://msdn.microsoft.com/library/ff731587.aspx">Scrum</a> through Visual Studio 2010 and <a href="http://www.blogger.com/goog_2113760520">Telerik's</a><a href="http://www.telerik.com/team-productivity-tools/products/teampulse.aspx"> Team Pulse product</a>. Scrum is an agile practice that gets the entire team involved in nearly the entire process from planning to tasks to conducting demos of the work completed.</div><div><br />
</div><div>With our first stab of Scrum, we will start with the following 2 week Sprint Schedule.</div><div><ul><li><b>Day 1</b>: <i>Sprint Planning Meetings</i></li>
<ul><li><b>Part I (4 hours max)</b>: Participants include Product Owner and Scrum Master</li>
<ul><li>Determine focus of the Sprint and flag possible Sprint Backlog items</li>
</ul><li><b>Part I (4 hours max)</b>: All Team Members participate</li>
<ul><li>Discuss in detail each flagged Sprint Backlog item</li>
<ul><li>Use Scrum Poker to estimate effort</li>
</ul><li>Determine actual Sprint Backlog and assign work to team members</li>
</ul></ul><li><b>Day 2-10</b>: <i>Daily Sprint Meeting (15 minute max)</i></li>
<ul><li>Team members answer:</li>
<ul><li>What have you done since the last meeting?</li>
<li>What will you do from now until the next meeting?</li>
<li>Is there anything holding up your work?</li>
</ul></ul><li><b>Day 6</b>: <i>Requirements Planning (4 hour max)</i></li>
<ul><ul><li>Participants include Product Owner and Scrum Master</li>
<ul><li>Add and edit the Product backlog</li>
<li>Additional stakeholders may be invited</li>
</ul></ul></ul><li><b>Day 10</b>: <i>Sprint Review and Retrospective (4 hour max)</i></li>
<ul><li>Demo functionality added from the Sprint.</li>
<li>Reflect on the Sprint to determine what worked, what didn't work and what would we change in the next Sprint.</li>
</ul></ul><div>Additionally we sprinkled into Sprint a few formal code reviews.</div></div><div><br />
</div><div>We had an <u>outstanding</u> Day 1 in our first ever Sprint. We played a little Scrum Poker, talked about backlog items and by the end of the day we all had our tasks outlined for the rest of the Sprint.</div><div><br />
</div><div><b>Links</b></div><div><ul><li><a href="http://www.scrumalliance.org/pages/what_is_scrum">Scrum Alliance: What is Scrum</a></li>
<li><a href="http://msdn.microsoft.com/library/ff731587.aspx">Visual Studio Scrum 1.0</a></li>
<li><a href="http://www.telerik.com/team-productivity-tools/products/teampulse.aspx">Telerik</a><a href="http://www.telerik.com/team-productivity-tools/products/teampulse.aspx"> TeamPulse</a></li>
<li><a href="http://www.crisp.se/planningpoker">Scrum Poker</a></li>
</ul></div>Adam Spicerhttp://www.blogger.com/profile/17987623191372261122noreply@blogger.com1