|
|
These blog entries are written by industry experts and leaders. We consider this content to be a good read for any software developer or web technologist.
January 2007 - Posts
-
I created a new web site project earlier this week using Visual Studio 2005 SP 1. Everything worked great except for building - when there was an error, no line numbers showed up in the Errors window! While this annoyance is sufferable when there are only a few pages, classes, and so forth in the project, as the number of pages and classes grew, the lack of line numbers made debugging increasingly difficult. There'd be some error message and then I'd have to track down where the error might reside out of the dozens of classes and pages that may have been modified since my last build. Urp.
After needlessly putting up with this nuisance for a couple days, I decided to get to the bottom of this. I found the following newsgroup post to microsoft.public.vsnet.debugging from an obvious Simpsons fan, someone going by the name of Rainier Wolfcastle:
“It turns out that there is some really helpful bug in Visual Studio 2005 whereby you don't get file names or line numbers in the Error List if your solution lives in a directory with parentheses in the path.”
Sure enough, the parent folder of the root of the web site application had a parenthesis in it. Once that was removed, line numbers returned to the Errors window. I wonder why this wasn't fixed in SP 1...
|
-
As I mentioned last week when ASP.NET AJAX 1.0 shipped, we are publishing the full source code to the ASP.NET AJAX product. This includes the source to the server-side ASP.NET integration (including the UpdatePanel, UpdateProgress, and ScriptManager controls, as well as the source to the Network Serialization code). The client-side ASP.NET AJAX JavaScript library (which we also call the "Microsoft AJAX Library") is being released under the Microsoft Permissive License (Ms-PL). This grants developers the right to freely customize/modify the library, as well as to redistribute the derivative versions of the JavaScript library for both commercial and non-commercial purposes. The code for the server-side ASP.NET AJAX 1.0 implementation was released this morning. You can download it here. It is being released under the Microsoft Reference License (Ms-RL). Included with the source code are debugger symbols for the shipped binary, which will allow you to step from your own code into the ASP. NET AJAX library while debugging, with line number and symbol data preserved. Note that the setup installs the source code locally on your machine within the "\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025\Source" directory. You can also obviously download (and modify) the source code for the ASP.NET AJAX Control Toolkit. It is built as a collaborative CodePlex Project that both Microsoft and non-Microsoft developers contribute code and work on together. Thanks, Scott P.S. I'm hoping on a plane to Europe in an hour for my presentations in Belgium and the UK, and will be out the rest of this week (it only took me 3 frantic hours to find my passport last night -- sheesh). As a result there will be some delays with blog comments (and my responses to them) while I'm away. 
|
-
I teach two ASP.NET classes through the Extension program at the University of California - San Diego, and one of the most common questions I am asked regarding Master Pages is, “How do I pass information from my Master Page to its content page (or vice-a-versa)?”
For example, in the ASP.NET Programming II class, students create a custom site map provider whose structure is based upon the data in the database. The Master Page contains navigation controls (a TreeView, perhaps, or a Menu) that uses this custom site map provider. The challenge is on administrative pages, where an admin might add, update, or delete the corresponding database data, the Master Page's navigation is rendered before the content page executes its database command to modify the site map structure. Consequently, the page's navigation is not up-to-date immediately after modifying the site map structure (although it picks up the changes on the next postback). This can be remedied by having the content page tell the Master Page, “Hey, you there! I just updated the site map data, so go ahead and rebind the site map data to your TreeView.“
This begs the question, How do you get the content page and Master Page talking? To address this question, I wrote up an article discussing different techniques: Passing Information Between Content and Master Pages.
|
-
I've averaged 13.5 posts per month over the last 37 months to arrive at today's post #500.I'm not sure if I'll make another 500 posts, but I have pages of notes for posts covering ASP.NET, AJAX, Windows Workflow, WCSF, and more. I also have enough material for at least 15 more "What's Wrong with This Code" posts, which several people have told me are fun and educational. One day, I might even finish my "Design Patterns - A Love Story" post. Then again, maybe that story should be purged from the Internet forever.
Thanks for reading!

|
-
One of my goals this year is to use video more with my blog. My theory is that video is often a better medium than text to walkthrough how something works, and can also help you avoid the tedium of reading though some of my really long blog posts... :-) Over the next few months I'm going to try and create a new video every other week or so on various topics. Many of these videos are going to involve first looks at some of the new features coming with Visual Studio "Orcas", which is our new release that will ship later this year. For today's video I decided to focus on introducing LINQ - which I think is one of the most exciting features coming with "Orcas". At a high-level, LINQ makes the concept of query a first class programming concept within .NET. Using LINQ you can easily query relational databases, XML files, as well as any plain-old .NET object. You can also easily use your own data source abstractions with LINQ to provide rich domain models for various data providers (for a great example of this check out Fabrice's LINQ to Amazon implementation that supports LINQ queries against Amazon data exposed via web-services). Both VB and C# include rich language integration with LINQ as part of the "Orcas" release, including full intellisense, compile-time checking, and debugging support. Watch or Download the Video This first video starts with a new project, and then demonstrates the basics of using LINQ against a SQL Database to build a simple data reporting page (including support for aggregate values computed from multiple tables, and efficient server-side paging within the database). You can watch the video online here (it is 24 minutes in length). Or you can download a .zip version of it here if you want to save and watch it locally. Note that it might take 30-60 seconds to buffer (since it is a large video). In the event that my server is swamped with requests, I'll update the location and post it on one of the Microsoft video servers later this week. For more information on LINQ (including the slide deck for a "Building ASP.NET Data Driven Application Using LINQ" talk of mine), please check out my previous post here. For other ASP.NET 2.0 Tips, Tricks and Tutorials please check out my ASP.NET Tips and Tricks summary listing page. Specifics Topics Covered in this Video My walkthrough in this video illustrates a number of new features: 1) A brief demonstration of some of the new WYSIWYG HTML designer capabilities (including split-view and a brief look at the new CSS manager - both of which I'll cover in more detail in the future in a separate video): 2) How to create classes that model data using the new VS "Orcas" ORM designer for LINQ to SQL: 3) How to use the new LINQ intellisense support within the VS "Orcas" code editor to get full intellisense and compilation support for queries: 4) How to use LINQ to SQL to create a data report that combines Product entity data with aggregate unit and revenue values computed from OrderDetail entities associated with the Product entities. This data report uses server side database paging to efficiently retrieve only 10 rows of data at a time (so that with a 100,000 row products table you only ever retrieve 10 rows of data from the database regardless of which page index you are on within a report): Future Videos I'll be drilling into LINQ some more with future videos (I barely scratched the surface with this one). Additional segments will include content on: - Type inference and the "var" keyword (and why that is so cool)
- Supporting Insert, Update and Deletes scenarios using LINQ to SQL
- Using SPROCs with LINQ to SQL
- Richer JOIN support with LINQ to SQL
- LINQ to XML and LINQ to Objects
- Using the new LINQDataSource controls and other ASP.NET Data Controls to easily create Web UI with LINQ
I'll also obviously have many more ASP.NET and web-related video topics to cover including: - The new HTML WYSIWYG Designer and CSS support
- Client-JavaScript Intellisense
- JavaScript Debugging
- ASP.NET AJAX Extender Support
- Database Dump and Upload Integration
- Unit Testing
- Multi-targeting support (showing how you can use VS "Orcas" to build ASP.NET 2.0 projects - without having to upgrade your framework/server)
Hope this helps, Scott P.S. If you have other topics and/or subjects you'd like me to drill in on with videos, please post them in the comments section of this post. 
|
-
-
When building an ASP.NET 2.0 application in Visual Studio 2005, I received the following error: “Cannot implicitly convert type 'string' to 'System.Web.UI.WebControls.TextBox'”. No line number, no source page informing me where to begin my search. And it had been a while since my last build so there was a lot of code and markup that could be the source of the problem.
A quick Google search turned up this entry by Sam Judson:
Strange ASP.NET 2.0 Error
While developing a new web site using ASP.Net 2.0 recently I came across this strange error on compilation. Cannot implicitly convert type 'string' to 'System.Web.UI.WebControls.TextBox'
It took my ages to work out what the hell was the problem, which string was it trying to convert?
The problem occurred because of the new Page.Title property. I had a TextBox whose ID was also set to Title. It was therefore trying to convert the string in the Page declaration into a textbox - not gonna work! This Title property is new for ASP.Net 2.0 so you might want to watch that one in your apps.
And that was the cause of my problem, a TextBox with an ID of Title. Once the ID was changed to something else, the project compiled without error. For more on the Page.Title property new to ASP.NET 2.0, see Dynamically Setting the Page's Title in ASP.NET 2.0.
|
-
In a couple of weeks I'll be presenting a full-day, hands-on conference/lecture/class/lab at the Robert Half Technology offices in Los Angeles. Together we will build a complete, functional, real-world blog engine that highlights recommended practices and ASP.NET 2.0-specific features. Topics discussed and implemented will include: using base page classes for encapsulating common functionality; logging and gracefully handling errors; building data access and business object layers; working with data through the ObjectDataSource; displaying and customizing data using the data Web controls; efficiently paging and sorting data; and employing caching to boost performance.
There is only room for 50 attendees and, at the time of this writing, close to half the spots are already taken. There are no computer workstations, so attendees are encouraged to bring their own laptops loaded with Visual Studio 2005 and SQL Server 2005 to follow along. (The free versions - Visual Web Developer and SQL Server 2005 Express Edition - will suffice.)
Here are the details:
- Cost: $45 (includes lunch; parking nearby for an additional $6-7 for the day)
- When: Saturday, Feburary 10, 2007, 9:00 AM - 5:00 PM (with a one hour lunch break)
- Where: Robert Half Technology, 10877 Wilshire Blvd, 4th floor (Suite 400), Los Angeles, CA 90024-4341, Phone: 310.209.6838 [map]
- Signup: To sign up, use the PayPal link at http://www.ladotnet.org/EventDescription.asp?133
Hope to see you there!
|
-
Below are a few links to some ASP.NET AJAX 1.0 resources, and answers to a few common questions I've seen with the ASP.NET AJAX 1.0 release: Great Free Resource: ASP.NET AJAX PDF Cheat Sheets Milan has updated his great ASP.NET AJAX PDF Cheat Sheets for the ASP.NET AJAX 1.0 final release. You can download his updated versions here. Make sure to subscribe to his blog to receive updates as new ones come out. Common Gotcha: Restart IIS and Flush your Browser Cache after Install I've seen a few cases where people are seeing older versions of the ASP.NET AJAX scripts being used even after upgrading to the ASP.NET AJAX 1.0 release. Often this manifests itself with a client-side JavaScript error about Sys.Debug not being found. Two things to check if you encounter this: 1) Make sure you restart IIS after you install ASP.NET AJAX (you can type "iisreset" on the command-line to-do this). If IIS already has an older version of the ASP.NET AJAX assembly loaded when the new one is installed, it will continue to use the already loaded older version until the next time the worker process is restarted. Restarting the worker process will cause it to pick up the new one. 2) Make sure you clear your browser cache if your browser is setup to store cached files forever. This will avoid you running into issues where your browser still has old versions of the .js files in its cache, and uses these instead of fetching the newer versions from the server. Common Gotcha: PageMethods now require the EnablePageMethods property to be set on the <asp:scriptmanager> control I've seen a few people run into an issue where their static AJAX Page Methods no longer seem to work when upgrading an ASP.NET AJAX RC application to the final V1 release. The reason for this is that ASP.NET AJAX Page Methods are no longer exposed by default on a page except if you set the "EnablePageMethods" property to true on the <asp:scriptmanager> control. For example: <asp:scriptmanager id="s1" EnablePageMethods="true" runat="server"/> Once you set this attribute to true, everything else will work the same. You can learn more about how to use PageMethods in the ASP.NET AJAX 1.0 documentation here. Common Gotcha: Validation Controls used within the <asp:updatepanel> control I've seen several people run into an issue where their validation controls no longer work inside an <asp:updatepanel> when upgrading to the RTM release. In the Beta1, Beta2 and the RC versions ASP.NET AJAX provided a set of "compatibility" controls that used the <tagMapping> web.config feature within ASP.NET to replace the built-in ASP.NET validation controls with AJAX aware controls that could be used within the <asp:updatepanel> control. This made it appear like you were using the standard ASP.NET validation controls within your site - when in reality you were using a new set of controls that added AJAX hooks. For the final release of ASP.NET AJAX, we decided to instead release a patch for ASP.NET 2.0 that adds the AJAX-awareness features directly into the real ASP.NET 2.0 validation controls. This ensures that the controls work in all scenarios, and is a much cleaner and more reliable solution. Unfortunately, though, this patch slipped a few weeks - and so wasn't pushed out via Windows Update in time for the ASP.NET AJAX 1.0 launch. As a temporary workaround until the patch is available, you can download the same compatibility validation controls we provided with the release candidate, and map the built-in ASP.NET validation controls to them using the <tagMapping> feature in your web.config file (just like in the RC release): <tagMapping>
<add tagType="System.Web.UI.WebControls.CompareValidator" mappedTagType="Sample.Web.UI.Compatibility.CompareValidator, Validators, Version=1.0.0.0"/>
<add tagType="System.Web.UI.WebControls.CustomValidator" mappedTagType="Sample.Web.UI.Compatibility.CustomValidator, Validators, Version=1.0.0.0"/>
<add tagType="System.Web.UI.WebControls.RangeValidator" mappedTagType="Sample.Web.UI.Compatibility.RangeValidator, Validators, Version=1.0.0.0"/>
<add tagType="System.Web.UI.WebControls.RegularExpressionValidator" mappedTagType="Sample.Web.UI.Compatibility.RegularExpressionValidator, Validators, Version=1.0.0.0"/> <add tagType="System.Web.UI.WebControls.RequiredFieldValidator" mappedTagType="Sample.Web.UI.Compatibility.RequiredFieldValidator, Validators, Version=1.0.0.0"/> <add tagType="System.Web.UI.WebControls.ValidationSummary" mappedTagType="Sample.Web.UI.Compatibility.ValidationSummary, Validators, Version=1.0.0.0"/>
</tagMapping> The validation controls will then work fine within <asp:updatepanel> controls, and behave exactly the same as with the release candidate version. You can download these compatibility controls here. Hope this helps, Scott 
|
-
I just wanted to give a quick update on a few presentations I'm giving in the weeks ahead: Brussels, Belgium: I'll be presenting two talks ("First Look at Visual Studio and ASP.NET 'Orcas' and "ASP.NET 2.0 and ASP.NET AJAX Tips and Tricks") in Belgium on February 1st (next Thursday). You can attend the event for free. More details can be found here. Reading, England: I'll be presenting four talks ("First Look at Visual Studio and ASP.NET 'Orcas', Building an end-to-end application using IIS7, ASP.NET 2.0, ASP.NET AJAX and VS 2005 Part 1 and 2, and "First Look at WPF/E") at the WebDD event at the Microsoft campus in Reading on Saturday February 3rd. Orlando, Florida: I'll be presenting the keynote and several breakout sessions at the ASP.NET Connections conference in Orlando from March 25th->28. If you haven't attended ASP.NET Connections yet, I highly recommend it. It will have 40+ great talks done by excellent speakers in a great location. You can learn more about it here. Hope to see some of you at the upcoming events! Scott 
|
-
In the last post I pointed out problems you can experience trying to handle workflow events in an ASP.NET page. Before we get to a working solution, let's take a look at another pitfall.
We know the default WF scheduling service will select a thread from the CLR thread pool to execute workflows asynchronously. Generally speaking, this isn't a good approach for server side applications because we can tie up too many threads. Instead, we use the ManualWorkflowSchedulerService. The manual scheduler lets us run workflows on the same thread that is processing the HTTP request. We just need to call RunWorkflow on the service whenever we need a workflow to execute.
It's tempting to think the manual scheduler can make life easier since we don't have to worry about threads. For instance, let's suppose we want any unhandled faults originating from inside a workflow to bring the current request to a screeching halt. We want unhandled exceptions! When a workflow faults and throws an exception, WF will catch the exception and raise a WorkflowTerminated event. This event will fire on the same thread as the request that ran the faulty workflow.
Knowing that we want to end requests with an error, we could try to use global.asax like the following. After all, if we throw an exception on the current request thread, we should create the yellow screen of death (assuming the Page doesn't have an exception handler). Note: I'm using global.asax just to make this simple.
void Application_Start(object sender, EventArgs e)
{
_workflowRuntime = new WorkflowRuntime("wfConfiguration");
_workflowRuntime.WorkflowTerminated +=
new EventHandler<WorkflowTerminatedEventArgs>
(_workflowRuntime_WorkflowTerminated);
_workflowRuntime.StartRuntime();
}
void _workflowRuntime_WorkflowTerminated
(object sender, WorkflowTerminatedEventArgs e)
{
throw e.Exception;
}
private static WorkflowRuntime _workflowRuntime;
The problem is that the WorkflowRuntime is dedicated to its job. The runtime is tasked with telling all the event subscribers that a workflow terminated, and it is not going to let some unhandled exception prevent the rest of the subscribers from missing events. The WF runtime swallows our exception. See Ken Getz's article for how to use GetInvocationList to achieve this behavior.
How can we communicate the exception back to the Page? Consider the following code.
void _workflowRuntime_WorkflowTerminated
(object sender, WorkflowTerminatedEventArgs e)
{
HttpContext.Current.Items["WorkflowResult"] = e.Exception;
}
Now the web form can pull the exception out of the HTTP request context. Problem solved!
Oh, but wait - we are spiraling out of control. Now the ASP.NET developer has to remember to start workflows with the manual scheduler, and check the request context for exceptions, and use such and such a communication service to raise events to the workflow.
If you are going to the trouble to use Windows Workflow in an ASP.NET application, then you have an architectural responsibility to abstract away these problematic and sometimes dangerous scenarios to the point that the ASP.NET developer doesn't even know there is a workflow driving the process. Bring a mediator to the party.

|
-
I am really excited to announce that the final release of ASP.NET AJAX 1.0 (aka "Atlas") shipped this morning. You can download it here. ASP.NET AJAX 1.0 ASP.NET AJAX 1.0 delivers a rich client-side AJAX library that provides cross platform, cross browser support for a core JavaScript type-system, JSON-based network serialization stack, JavaScript component/control model, as well as common client JavaScript helper classes. ASP.NET AJAX also delivers a rich server-side library that integrates AJAX functionality within ASP.NET, and enables developers to easily AJAX-enable existing ASP.NET 2.0 sites with minimal effort. ASP.NET AJAX is available for free, and can be used with ASP.NET 2.0 and VS 2005. It is a fully supported Microsoft product, and is backed by a standard 10 year Microsoft support license (with Microsoft Product Support available via phone 24 hours a day x 7 days a week). ASP.NET AJAX Control Toolkit In addition to the fully-supported ASP.NET AJAX 1.0 release, you can use the more than 30 free ASP.NET AJAX enabled controls available within the ASP.NET AJAX Control Toolkit. The control toolkit is a shared-source collaborative project built together by a team containing both Microsoft and non-Microsoft developers (visit the CodePlex Project to learn more, or volunteer to contribute). All source for the controls is provided completely for free (with full re-use and modification rights). The majority of controls within the ASP.NET AJAX Control Toolkit leverage the "Control Extender" pattern that the core ASP.NET AJAX library introduces, and which delivers a super powerful way to easily enable specific AJAX scenarios on a site with minimal effort. For example, consider the scenario where you want to add a cool AJAX calendar picker to a page (note that the browser below is Opera): To enable this with the ASP.NET AJAX Control Toolkit you can simply add a <ajaxToolkit:CalendarExtender> control to a page and point it at a textbox to store the date (no additional code required): <asp:TextBox ID="DateTextBox" runat="server" /> <ajaxToolkit:CalendarExtender ID="Calendar1" runat="server" TargetControlID="DateTextBox" /> The ASP.NET AJAX Control Toolkit will continue to grow and expand in the months ahead - with more controls, features (and bug-fixes) being added every month. The new version of the AJAX Control Toolkit that ships today adds support for 4 new controls to the Toolkit: <ajaxToolkit:CalendarExtender>, <ajaxToolkit:MaskedEditExtender>, <ajaxToolkit:TabContainer>, and <ajaxToolkit:AutoCompleteExtender>. You can try samples of them all out online here. (Special thanks to Ron and Fernando for implementing the new Calendar, Tab, and MaskedEdit controls added this month). ASP.NET AJAX 1.0 Source Release In addition to shipping the source code for the ASP.NET AJAX Control Toolkit controls, we are also releasing all of the source code for the fully supported ASP.NET AJAX 1.0 release. Specifically: We are releasing the client-side ASP.NET AJAX JavaScript library (which we also call the "Microsoft AJAX Library") under the Microsoft Permissive License (Ms-PL). This grants developers the right to freely customize/modify the library, as well as to redistribute the derivative versions of the JavaScript library for both commercial and non-commercial purposes. To help with debugging and development, we are also releasing all of the source code for the server-side ASP.NET AJAX 1.0 implementation (including the UpdatePanel, UpdateProgress, ScriptManager, and Network Serialization code) under the Microsoft Reference License (Ms-RL). Changes between the ASP.NET AJAX Release Candidate and RTM Build We made a number of improvements and bug fixes between the ASP.NET AJAX Release Candidate and RTM builds. These included: - Performance and scalability improvements for shared hosting scenarios.
- Globalization fixes to ScriptManager and ScriptResource handler to support date & number parsing and UI culture fallback.
- Updated ScriptResource handler to support automatic enabling/disabling JavaScript compression based on browser type.
- Support for substitution caching to enable more fragment caching scenarios.
- Additional bug fixes and overall robustness improvements.
More complete documentation covering all changes can be found on the http://ajax.asp.net website. If you have installed previous versions of ASP.NET AJAX on your system, I recommend that you delete the cached VS schema files for control markup that VS maintains to provide HTML view intellisense. This will ensure that your HTML source editor Intellisense for the ASP.NET AJAX controls is correct and doesn't get lost (otherwise it might incorrectly use the old values from the Beta2 release and generate errors). - With Windows XP you do this by deleting all files in this directory: c:\Document and Settings\[YourUserName]\Application Data\Microsoft\VisualStudio\8.0\ReflectedSchemas
- With Windows Vista you do this by deleting all files in this directory: c:\Users\[YourUserName]\AppData\Roaming\Microsoft\VisualStudio\8.0\ReflectedSchemas
Future Plans While the core ASP.NET AJAX 1.0 release is now officially shipped, we are definitely not slowing down. :-) All of the ASP.NET AJAX 1.0 features will be integrated directly into the next release of ASP.NET (codename: "Orcas"). Visual Studio "Orcas" will also provide client-side JavaScript intellisense, JavaScript compilation checking, and rich JavaScript debugging support for ASP.NET AJAX scenarios. We are also already at work on the next ASP.NET AJAX release, and will continue to add new features and improvements to the supported ASP.NET AJAX core. You can already start using many of these new features with the ASP.NET AJAX Futures CTP (available for download now on the ASP.NET AJAX site - it also supports a "go live" license). Summary We are really excited about having the ASP.NET AJAX 1.0 release finally out. It will dramatically simplify adding rich AJAX functionality to ASP.NET 2.0 applications, and is going to significantly improve user experience for customers. We are really looking forward to seeing all the great applications you build with it! Thanks, Scott 
|
-
I've had the opportunity lately to work with Hummingbird's Document Management (DM) system on one of my projects at Mimsware. In particular I was tasked to install, configure, and learn about their Automated Email Management (AEM) system in a test environment. What is AEM? It is basically a plugin for MS Exchange that makes it possible for all emails in an organization to be automatically archived into the Hummingbird DM system according to flexible rules that you define. The goal for some organizations will be to make legal compliance of email retention automatic, and any necessary legal discovery very easy, especially important in a government organization with open record laws. Other organizations may also be interested in simply making email work like all other documents, so that one document management system can be used to store and search all types of documents in the organization. I was able to get AEM working effectively, but there were also several aspects of the installation and configuration that were not documented well, or which required a lot of trial and error, so I want to share some of the lessons learned. We are using DM version 5.1.0.5 SR6, so that is what I installed for AEM to begin with, but at least on my system it would not start up successfully after an apparent successful install, so I had to use patch SR6 MR2. I suppose some will say that you should always use the latest version, but a Hummingbird installation is a very complex beast, so once you have something in place that works for you, its a big deal to update everything. Luckily in this case I was able to only install the new version for just AEM and leave the rest of the DM system on the current version, but even that was something that had to be thoroughly tested, and there may still be some unknowns. Once I had it installed it quickly became a very long and involved process to configure things correctly, but most of this was documented and in most other cases the log was sufficient. I think the biggest problem is that everything is too configurable and that there are no smart defaults, and yet for this type of system there are a lot of defaults that just seem to be obvious. For instance, they provide a default email profile, with fields to store the from, to, cc, bcc, received date, and send date, but none of these are configured for you so you have to specify both the profile and every one of these fields. We also had some other custom fields that had to be set, and of course I would expect that to be my task, but I just don't see why they can't have the standard email fields defaulted to begin with. But ignoring my custom fields for now, which were very easy to figure out with their log's help, here is what I determined to be the optimal set of profile values for the standard email fields: PROFILE=(DEF_MPROF), TYPE_ID=(EMAIL), ABSTRACT=(%s), EMAIL_FROM=(%f), EMAIL_TO=(%t), EMAIL_CC=(%h"cc"), EMAIL_BCC=(%h"bcc"), EMAIL_RECEIVED=(%h"datereceived"), EMAIL_SENT=(%h"date") The Type Id might be something else for someone else, since this was a custom type that I created myself, but I also think it just makes good sense to define an Email type to best differentiate email documents. The Abstract value, which is used for the document description, and wasn't documented anywhere that I could find, may also be something that you may want to set differently -- I've simply set it to the subject. On the other hand, all of the other values seem non-debateable to me since of course you want the from value set to the from address, and so one for the to, cc, bcc, received date, and sent date. I should point out though that they do not document the dates anywhere, which seems to be an important oversight since these are pretty standard email fields, but I was able to figure out the sent date myself since it is a normal email header. The received date on the other hand is very simple once you know what to do, but it took support a while to get this one found for me, and the received email header is quite involved so it was not something I could figure out myself. At this point I had it all installed and configured so that I could successfully send and receive emails and see them captured and stored in Hummingbird DM according to the rules that I had setup. But there were still a few other problems that became apparent in testing -- the first being that email attachments were not getting profiled separately, which was an option that I had specified I wanted enabled during the installation. It turns out that the installation program did not set a registry value correctly, and support was able to identify this pretty quickly, but I'm still not sure why this wasn't set correctly by the installation program. I should also point out that this registry setting, and many others, are well documented, including some that have to be manually set since they do not have options in the installation, like full-text search. And that left me with everything working correctly with the exception of one advertised feature that was unable to work in my case, although its also a feature that we can probably do without for the time being. The advertised feature is that you can specify folder names that don't yet exist and AEM will automatically create them on the fly, which I can see some shops wanting to better organize emails by sender or receiver or some other dynamic criteria. My understanding on this issue, after many discussions with support, is that this feature does work in environments that do not have custom fields of their own added to the default profile form, but its our customizations that are causing it not to work. Of course it does beg the question of how they never accounted for this situation before, since I would bet just about every Hummingbird setup involves some customizations, which they also strongly encourage by the way. Oh well, its now on their list to fix, and its probably something we can live without for now, but hopefully by documenting here, along with my other lessons learned, I can save someone else out there some time. 
|
-
For years I've had a very low-end Lexmark InkJet printer, the kind that sells for $39.95, which is just a shade more than what they charge per ink cartridge. In retrospect, I really should have ditched it earlier. It was painfully slow in printing and I was unable to share it on the network, meaning that if my wife wanted to print something she'd have to copy the file(s) to my computer and I'd print them. And did I mention it was slow? But if you don't work in an office where they have sleak, ultra-fast, network-shared printers, you don't know what you're missing. So I was content with my little Lexmark and my wife, after coming home from an office full of high-end laser printers had to copy anything she needed to print to my machine and then wait several minutes as the printer caughed them out.
Finally we decided enough was enough and went looking for an All-In-One option to replace our printer and fax machine and to add scanning and copying capabilities. We ended up settling on the HP LaserJet 3050 All-In-One (shown on the right), which retails for $299.
Not counting furniture moving, installation and setup was a breeze. Just plugged in the various cords, plugged in the printer to my machine via the USB cable, and we were off and running. Faxing, copying, scanning, and printing are all very straightforward, simple, and FAST. In the time it would take the ol' Lexmark to churn out a single page, this puppy can put out reems of paper. It just sucks in the paper and spits it out, taking a second or two. Yeah, yeah, this is probably no big deal to those of you who haven't been living with outdated technology, but for yours truly, this alone has made the purchase more than worthwhile.
There are a couple of things that are less than ideal regarding the 3050:
- No USB-to-printer cable included. I don't know if any printer manufacturer includes this anymore. I used my old one from the Lexmark printer (which I had to buy separately back in the day). In any event, I think most people would rather HP (or Lexmark or whomever) would charge $5 or $10 more and just include the damn cable rather than having you get home, get to setting it up, and then realizing, “Cripes, it's back to the store for me.“
- No direct connection to network. The only way to hook up the 3050 model is through a USB cable, which is no biggie since it's hooked up to my always-on computer. But in a more traditional network setting, it's obviously ideal to have the printer hooked up to the network rather than a computer. To get the network hookup, you have to upgrade to the 3052 model, which is $100 more. $100 more also buys you a flatbed scanner/copier, which is nicer than the sheet feed option on the 3050. And I was just about ready to pony up the extra $100 for the 3052 and then found out that the 3052 doesn't include fax capabilities! If you want to fax and have a network jack and a flatbed scanner then you need the 3055, which is yet another $100. A 66% increase in the base price for a network jack and a flatbed scanner seemed a little too steep for this ol' cheapskate.
In any event, I really have liked the 3050 and am sure the 3052 and 3055 are just as good models. Highly recommended!
|
-
This weekend was a really exciting one for the VS Web Tools team. On Saturday they checked in their new HTML and ASP.NET WYSIWYG designer into Visual Studio. This designer is a major, major improvement over previous HTML designers within Visual Studio, and will be a shared component used by both Visual Studio and Expression Web Designer going forward. Among other things, the new HTML designer provides: - Split View Support (the ability to have both HTML Source and WYSIWYG design open simultaneously)
- Extremely rich CSS support (CSS property window, CSS inheritance viewer, CSS preview, and CSS manager)
- Dramatically improved view switching performance (moving from source->html design mode is now nearly instantaneous)
- Support for control designers within source view (property builders, event wire-up and wizards now work in source view)
- Richer ruler and layout support (better yet, values can be automatically stored in external CSS files)
- Designer support for nested master pages
Below is a screen-shot with a lot of the new features in action: We actually began working on the new designer in November 2004 - almost a year before VS 2005 shipped (there was a lot of work todo!). Mikhail Arkhipov was the dev manager who led and architected the work. You can learn more about the project and see some initial screen-shots of the new designer in his blog post here. I'm planning to record some videos over the next few weeks that show off the new HTML designer as well as other cool new "Orcas" features. The next "Orcas" CTP will also contain the new designer (and a ton of other new features) to try out yourself. Hope you enjoy it, Scott 
|
-
-
Once you have the WorkflowRuntime up and running in an ASP.NET application or web service, you'll want handle key life cycle events like WorkflowTerminated and WorkflowCompleted. I want to warn you about some common pitfalls I've seen.
There are two subtle but extremely dangerous problems in the following code.
protected void Page_Load(object sender, EventArgs e)
{
// get a reference to our WorkflowRuntime singleton
WorkflowRuntime runtime = ApplicationInstance.WorkflowRuntime;
// wire up an event handler
runtime.WorkflowCompleted +=
new EventHandler<WorkflowCompletedEventArgs>
(runtime_WorkflowCompleted);
// create and start a new workflow
WorkflowInstance workflow;
workflow = runtime.CreateWorkflow(typeof(SomeWorkflow));
workflow.Start();
// ask the manual scheduling service to execute the
// workflow on this very thread
ManualWorkflowSchedulerService scheduler;
scheduler = runtime.GetService<ManualWorkflowSchedulerService>();
scheduler.RunWorkflow(workflow.InstanceId);
}
void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
// depending on what the workflow did for us, this is where we would
// tell the user the final price, or approve their document, or whatever
// workflowy thing that might have happened
}
Think: Singletons and event handling. The WorkflowRuntime will typically be a singleton in an ASP.NET app. In the WF RTM version, you can have multiple WF runtimes executing inside the same AppDomain (this wasn’t true in the betas), but chances are you don't want to pay the performance overhead of spinning up a new WF runtime for each request. Thus, we have a single and globally accessible WF runtime. For questions about the ManualWorkflowSchedulerService, see my article on hosting Windows Workflow. This scheduler allows us to run the workflow instance synchronously - on the same thread as the request.
Problem #1: Someone Just Expensed a Ferrari
The WorkflowCompleted event will fire for any workflow that completes, not just the workflow we are executing inside this page (or web request).
Let's say the workflow is running some business rules to automatically approve or reject expense reports. This usually requires a human bean counter to get involved, but stick with me for a second and pretend it's all done in silicon. Let's say the workflow indicates approval or rejection with the OutputParameters property of the WorkflowCompletedEventArgs.
User Joe submits an expense report for his new red stapler. At the same time, I submit an expense report for a red Ferrari Enzo. There are two pages executing on the server, and both subscribed to the WorkflowCompleted event. If things work out just right, Joe's workflow will complete first and approve his expense report. The runtime will raise the completed event, which both pages handle. Since Joe's workflow indicated approval, Joe will soon be stapling papers while I get to go 0-60 in less than 3.5 seconds.
Problem #2: We Need More Power, Scotty!
To fire the completed event, the WorkflowRuntime maintains a reference to the Page object. We should assume the WorkflowRuntime, as a singleton, will live for the duration of the AppDomain. Assuming the Page object never un-subscribes from the completed event, it will be in memory for the duration of the AppDomain, too. The garbage collector can't take the Page out of memory while it's being referenced by the WF runtime. RAM will start to disappear over time.
Even worse, with each request another instance of this Page class will wire itself to the WorkflowRuntime, and each time a workflow completes the WF runtime will need to raise the event to all these zombie page objects. This will keep the CPU busy, too.
It won't be long before the server is sucking mud, and the company is out of money.

|
-
The Atlanta Code Camp was today, so I finally got to give my LINQ and O/R Mapping talk that I've been preparing. I tried to have minimal slides so that I could do a deep dive into real code, but I still went a little too long. The slides look great on my own PC, and in fact they're mostly some I stole straight from other LINQ presentions. But the overhead I was using made the text nearly unreadable for some reason, which made me take longer on the slides. It also made some of the standard VS color syntax unreadable, with the work-around being to select that code. I small the same problem with another speaker in the same room, so I guess it was the projector, but very frustrating. In the end I still got to hopefully show a fair amount of LINQ to SQL, but I had really hoped to show more. I also made sure I gave a glimpse at SqlMetal and LINQ to Entities, but both of those were meant to be just glimpses. Finally, I briefly demoed my new "real" example application written with LINQ to SQL which is included in my download. This example shows off my own POCO objects with an external XML Mapping file, instead of the ugly code gen with attributes. Its also a "real" app that consumes the LINQ to SQL with WinForms grids, drop-down filtering, and create, update, and delete. Note that it assumes the May 2006 CTP, but I'll update it to the next one when it comes out, hopefully next month. Its also nearly identical to my existing "real" example app downloads that I have for my own ORMapper and NHibernate. 
|
-
One of my goals is to read more history books, I have a ton of them sitting on my bookshelf and I just need to get better about grabbing one of them when I go looking for the next book to read. I have had Flags of our Fathers sitting on the book shelf for quite sometime, but when I saw the movie was coming out I wanted to make sure I read it before I saw the movie. (I finished the book a couple months ago and still haven’t seen the movie yet)
James Bradley was in a unique position to write this book since his father was one of the flag raisers captured in the photo on the cover of the book. This book is more about the people in this photo than about the actual battle of Iwo Jima, although there is a great deal about the battle as well.
Most of the books I have read about World War II have focused on the European theater so it was refreshing to read a book about the Pacific theater. The book starts out detailing the lives of the six men in this photo before the war. It goes on to talk about their path into the military, their role in the invasion, and then the circumstances that took them to the top of that mountain on Iwo Jima. The book then goes on to detail what happens to each of the different men in the photo, and most of the stories don’t end very well. I am sure there are plenty of books out there that do a much better job of covering the battle of Iwo Jima itself, but this book is unique in that it looks at the battle (and all of WWII) through the eyes of a number of individual men who were brought together for a press photo that changed their lives and inspired America.
Now I just need to see the movie.
-James 
|
-
I have been alternating between reading a current novel and a classic the last couple of months, Heart of Darkness is one of the recent classics I read for the first time. Penguin has a series of books called the “Great Books of the 20th Century” and I am working my way through all of the books in that series.
Heart of Darkness is a haunting tale about a trader trying to make his way into the jungle and reaching not only his limits, but the very limits of society. I know some people who found this book hard to read, but I thoroughly enjoyed it. I particularly enjoyed how well the writing style of the book worked to enhance the feeling of lawlessness and chaos in the Belgian congo. The book is first and foremost about the ill effects of colonialism on both the natives and the colonizers, which in 1902 when this was published was a fairly controversial view.
The story and writing remind me of H.P. Lovecraft in some ways, although much less supernatural the nightmarish quality is very similar.
-James 
|
-
I have six books sitting next to me that I haven’t blogged about yet, so it’s time for a marathon blog session to clear out the queue. The book I most recently finished was Haunted by Chuck Palahnuik. Chuck is one of my favorite authors. I have read all of his stuff but I had been putting off reading this one for some time. Mostly because I hadn’t heard great things about it.
Haunted is a novel that includes a mix of poems and short stories about each of the characters in the novel. My theory is that Chuck planned on doing a book of short stories, but someone talked him into trying to write a novel around it. I am sure the publisher was getting tired of his non-novel books like Stranger Than Fiction: True Stories and Fugitives and Refugees which usually don’t achieve the commercial success a proper novel does.
The short stories are classic Palahnuik, they are strange, off-beat, filled with odd facts and events, and remind me of much of his earlier work. There is even one short story that I blogged about years ago because the story was that people were fainting while he read it on the book tour.The poems are decent, but nothing special. The novel itself is OK, but hardly up to the Palahnuik’s normal work.
The novel section is about a group of people who go to a writer’s retreat that takes a turn for the worse, the problems are agitated by the fact that everyone sees this as their passage to pop culture stardom. They start to make the situation worse on purpose to make their story more sensational, meaning better book deals, talk shows, and movies. While it is obviously a statement on “reality TV” culture, it just doesn’t have the same qualities as most Palahnuik stories. The characters are definitely strange, but you don’t relate to them the way you do with his other characters. The writing style even seems different, many of his other stories are incredible strange but always sound like they could be true. This story doesn’t feel real at all. So if you are a Palahniuk fan I would read the book, but don’t expect much from the novel or poems and just enjoy the short stories.
P.S. If you are wondering his name is pronounced Paula-Nick. (he wrote about how his parents taught him to pronounce it using his grandparents names)
-James 
| |
|