Scott Hanselman

ASP.NET Futures - Generating Dynamic Images with HttpHandlers gets Easier

August 21, '08 Comments [24] Posted in ASP.NET | ASP.NET Dynamic Data | ASP.NET MVC
Sponsored By

There's a treasure trove of interesting stuff over at http://www.codeplex.com/aspnet. It's a bunch of potential future stuff that the ASP.NET team is working on. That's where you can get builds of ASP.NET MVC, Dynamic Data Futures, and new AJAX stuff.

Two days ago a new CodePlex release snuck up on the site. It's a potential new feature, so it could go nowhere, or we could make T-shirts and sing its praises. Could go either way. No promises.

Justin Beck, an ASP.NET intern, prototyped and design it, then Marcin Dobosz, an ASP.NET Developer tidied it up nicely. Right now it's called ASP.NET Generated Image and you can get a release today.

Why should you care?

I've done a lot of HttpHandlers that generate images. It's usually pretty tedious. When I was working banking, I wrote an example HttpHandler that would take two Check Images (back and front) and composite them into a single image on the server side, then serving up the composite. Usually you're messing around in with MemoryStreams and Images, and then you serialize the result out to the Response.OutputStream, making sure the MIME Types are set appropriately. If you're really clever, you'll remember to do some client-side and appropriate caching, but I rarely see that in the wild.

So what have Justin and Marcin done here?

First, they've created a control with a little design mode "chrome" that makes getting started easier. The control is actually an extension of <asp:image/> that creates an HttpHandler and wires up the the src= attribute to the handler. If that were all, it'd be cute. However, second, and most importantly, they've created a base class that can do caching, transformations and parameter passing for you. It's really nicely factored, IMHO.

Here's a simple example. Put one of these GeneratedImage Controls on the page, and click on it...

Screenshot of the Context Menu of the GeneratedImage Control 

Next, click "Create Image Handler." You'll get this in the markup, and a new file in the Project:

public class ImageHandler1 : ImageHandler {

public ImageHandler1() {
// Set caching settings and add image transformations here
// EnableServerCache = true;
}

public override ImageInfo GenerateImage(NameValueCollection parameters) {
// Add image generation logic here and return an instance of ImageInfo
throw new NotImplementedException();
}
}

All I need to do now is override GenerateImage. Any parameters to the control will be in the NameValueCollection. I just need to return a new ImageInfo, and the constructor for ImageInfo can take either an Image, a byte[] or an HttpStatusCode. Clever.

Here, I'll add some text:

<cc1:GeneratedImage ID="GeneratedImage1"
runat="server" ImageHandlerUrl="~/TextImageHandler.ashx" >
<Parameters>
<cc1:ImageParameter Name="Hello" Value="text in an image" />
</Parameters>
</cc1:GeneratedImage>

As I said, that parameter is passed in, and it come from <% %> code or DataBinding or whatever. It doesn't care. Now, I'll draw on an image:

public class TextImageHandler : ImageHandler {

public TextImageHandler() {
this.ContentType = System.Drawing.Imaging.ImageFormat.Png;
}

public override ImageInfo GenerateImage(NameValueCollection parameters) {
// Add image generation logic here and return an instance of ImageInfo
Bitmap bit = new Bitmap(300, 60);
Graphics gra = Graphics.FromImage(bit);
gra.Clear(Color.AliceBlue);
gra.DrawString(parameters["Hello"], new Font(FontFamily.GenericSansSerif, 16), Brushes.Black, 0, 0);
return new ImageInfo(bit);
}
}

Which results in...

Picture of a dynamic generated image with text inside it 

Slick. What else can I do easily? Let's right-click on the ImageHandler base class and see what it looks like:

namespace Microsoft.Web
{
public abstract class ImageHandler : IHttpHandler
{
protected ImageHandler();

public TimeSpan ClientCacheExpiration { get; set; }
public ImageFormat ContentType { get; set; }
public bool EnableClientCache { get; set; }
public bool EnableServerCache { get; set; }
protected List<ImageTransform> ImageTransforms { get; }
public virtual bool IsReusable { get; }

public abstract ImageInfo GenerateImage(NameValueCollection parameters);
public void ProcessRequest(HttpContext context);
}
}

ImageTransforms? Hm...you can also setup a collection of ImageTransform objects into a little mini-image processing pipeline to do whatever you like.

Here we add a copyright watermark dynamically. The Transform is added in the constructor in this example.

public class TestCustomImages : ImageHandler {

public TestCustomImages()
{
this.ImageTransforms.Add(new CustomImageTransforms.ImageCopyrightTransform { Text = "Copyright Me! 2008" });
this.ContentType = System.Drawing.Imaging.ImageFormat.Png;
}

public override ImageInfo GenerateImage(NameValueCollection parameters) {
Bitmap pic = new Bitmap(200, 50);
Graphics gra = Graphics.FromImage(pic);
gra.Clear(Color.SkyBlue);
return new ImageInfo(pic);
}
}

The source for the CustomTransform, and for all the samples and the preview assembly that makes it all work is up on CodePlex now. If you've got ideas, find bugs, or think it's cool, leave a comment here and I'll make sure they get them. You can also leave bugs in the Issue Tracker on CodePlex.

Here's what the roadmap document says they've got planned...

  • Add Item Templates for an Image Handler
  • Providing parameter type inference for the handler instead of a Name Value Collection.
  • Giving you control of transforms, caching inside of your Generate Image Method.

Does it work with ASP.NET MVC?

Gee, I dunno. Let's see. Remember that if you're using ASP.NET MVC with the WebFormsViewEngine, as long as there's no Postback, some Server Controls can still work. This just might, as it renders on the first load.

I added the ASHX handler file to my MVC project, referenced the DLL, made sure to register the tag prefix and it mostly worked. The design service isn't working, saying something about "could not be set on property ImageHandlerUrl," but I'm encourage I got this far. Let's encourage them to keep MVC in mind!

image

Cool. Have at it at CodePlex. No warranty express or implied.

Technorati Tags: ,

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

New Outlook VSTO AddIn: How to disable Reply To All and Forward in Outlook 2007

August 21, '08 Comments [6] Posted in Source Code | Tools
Sponsored By

2010 UPDATE: Gavin has released an updated version of his No Reply To All Add-In on the Microsoft Research Site. Go get it free!

Last October I posted a Macro-quasi-hack to Disable Reply To All and Forward in Outlook within your own company network. The technique uses a macro to flip a metadata bit in a message.

Of course the only REAL way truly to disable Reply to All and Forward is to use IRM (Intellectual Rights Management) in Outlook 2003/7. However, this technique was useful to a lot of people as it is super simple and can stop those "knee-jerk" Reply to Alls.

Anyway, after this post Gavin Smyth of Microsoft Research emailed me and said:

"However, it's still such a useful idea that I finally got round to writing a C# addin to do it (vaaaassst overkill, I know, but it was easy) - toggle buttons (one for reply, one for forward) on the ribbon that set the two flags appropriately."

Cool. He's written his first Visual Studio Tools for Office (VSTO) AddIn, and it's a good tutorial on how to write one!

image The general idea os:

  • Start with the VS Outlook Add-In project wizard
  • Add the ribbon group & buttons
  • Create click event handlers for both, replicating what was in your my blog posting

Poof. Package and Deploy. It's really obscenely easy. Actually, way easier than the macro way I did it.

Now my Messages have these nice shiny new icons:

NoReplyButtons 

The source is trivial:

using System;
using Microsoft.Office.Tools.Ribbon;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;

namespace NoReplyAllAddin
{
public partial class Ribbon : OfficeRibbon
{
public Ribbon() { InitializeComponent(); }

private bool SetActionFromButton( object sender, object context, string action )
{
bool oldValue = false;
Outlook.Inspector inspector = context as Outlook.Inspector;
if( inspector != null )
{
Outlook.MailItem msg = inspector.CurrentItem as Outlook.MailItem;
if( msg != null )
{
oldValue = msg.Actions[ action ].Enabled;
RibbonToggleButton btn = (RibbonToggleButton)sender;
msg.Actions[ action ].Enabled = !btn.Checked;
}
}
return oldValue;
}

private void OnClickNoReplyAll( object sender, RibbonControlEventArgs e )
{
SetActionFromButton( sender, e.Control.Context, "Reply to All" );
}

private void OnClickNoForward( object sender, RibbonControlEventArgs e )
{
SetActionFromButton( sender, e.Control.Context, "Forward" );
}
}
}

You can download the setup and/or the source for Gavin's "No Reply for Outlook 2007"  over at his Software Utilities site. Thanks to Gavin!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Weekly Source Code 32- Atom, AtomPub and BlogSvc, an AtomPub Server in WCF

August 21, '08 Comments [7] Posted in ASP.NET | Source Code | Web Services | Windows Client | WPF | XML
Sponsored By

In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you thirty-second in a infinite number of posts of "The Weekly Source Code."

UPDATE: The BlogSvc.NET code has been refactored considerably, so consider checking out the Recent CheckIns to see what's changed..

BlogSvcBlogSvc.NET - The AtomPub Server for WCF and .NET

Much respect to people who not only release Open Source Software, but also take the time to get a nice, clean logo for their project as BlogSvc.NET did. It's written by Jarrett Vance and the code is up on CodePlex with Documentation and details on the main BlogSvc.NET site.

It also appears that the site at http://www.blogsvc.net is also the Demo Site for BlogSvc itself! Actually, if you download the source, you're downloading the complete implementation of the BlogSvc.net website. Booyachaka. Much respect.

Since the project uses Atom and AtomPub he can work against it using Windows Live Writer. You can learn all about how WLW likes Atom by reading the series of posts the most excellent Joe Cheng of the Live Writer team did on how this is all implemented.

Made it this far and wondering what the heck it all means? Let us turn to Wikipedia who gets it mostly right this time.

The name Atom applies to a pair of related standards. The Atom Syndication Format is an XML language used for web feeds, while the Atom Publishing Protocol (short AtomPub or APP) is a simple HTTP-based protocol for creating and updating web resources.

One way to look at it is that RSS is as a syndication format that looked like XML, but didn't really respect XML at its heart. Atom does. For publishing to blogs or content sites, the Blogger/MetaWeblog APIs are based on XML/RPC (a protocol that you either love or it makes you ill. Or both) while AtomPub is based on the RESTmodel and Atom and went through a more Standardsy adoption process. Ultimately it's a safe bet to use Atom and/or AtomPub. Everyone's pretty much on board. Microsoft got on board earlier this year. My hero Pablo Castro, the Principal Architect of ADO Data Services is supporting AtomPub in his project.

That said, BlogSvc is:

"...an open source implementation of the Atom Publishing Protocol. It is built on top of a provider model. There are providers for the file system and databases. The service is compatible with Live Writer."

Enough chatter, let's see some code. It's 0.3, but it's marching right along. When Jarrett starts using .NET 3.5 SP1, he'll likely get to do some "coding via subtraction" and swap out a lot of the boring Atom Object Model code with the new System.ServiceModel.Syndication and use the ServiceDocument. Jarreyy might be able to remove most of his "BlogService.Core" project. The new 3.5 SP1 stuff includes Atom and AtomPub object models as well as an Rss20 object model. It'll be interesting to see if those new object models can stand up against Argotic.

He's got a pretty comprehensive IAtomPub namespace with the UriTemplates that correspond to the "tag" URI Scheme from RFC 4151 that he's complying with.

[ServiceContract]
public interface IAtomPub
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}")]
Stream CreateResource(string workspaceName, string collectionName, Stream stream);

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}/*")]
Stream Annotate(string workspaceName, string collectionName, Stream stream);

[OperationContract]
[WebGet(UriTemplate = "{workspaceName}/{collectionName}/*")]
Stream RetrieveResource(string workspaceName, string collectionName);

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{workspaceName}/{collectionName}/*", Method = "PUT")]
Stream UpdateResource(string workspaceName, string collectionName, Stream stream);

[OperationContract]
[WebInvoke(UriTemplate = "{workspaceName}/{collectionName}/*", Method = "DELETE")]
void DeleteResource(string workspaceName, string collectionName);

[OperationContract]
[WebInvoke(UriTemplate = "{workspaceName}/{collectionName}/*", Method = "HEAD")]
void HeadResource(string workspaceName, string collectionName);

[OperationContract]
[WebGet(UriTemplate = "service")]
AppService RetrieveService();

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "service", Method = "PUT")]
AppService UpdateService(AppService serviceDoc);

[OperationContract]
[WebGet(UriTemplate = "{workspaceName}/{collectionName}/category?scheme={scheme}")]
AppCategories RetrieveCategories(string workspaceName, string collectionName, string scheme);

[OperationContract]
[WebGet(UriTemplate = "{workspaceName}/{collectionName}")]
AtomFeed RetrieveFeed(string workspaceName, string collectionName);
}

Now, let's look at CreateMedia which would be called as a part of CreateResource for any type of data that's not an Atom content type. CreateMedia is the kind of thing you'd want to do if you were attaching a picture or a video to your blog post.

public AtomEntry CreateMedia(string workspace, string collection, Stream stream)
{
try
{
if (!Authenticate(true)) return null;
string slug = WebOperationContext.Current.IncomingRequest.Headers["Slug"];
string contentType = WebOperationContext.Current.IncomingRequest.ContentType;
string etag;
AtomEntry entry = Atom.Provider.GetService().GetCollection(workspace, collection).CreateMedia(stream, slug, contentType, out etag);
WebOperationContext.Current.OutgoingResponse.ContentType = Atom.ContentTypeEntry;
WebOperationContext.Current.OutgoingResponse.Headers["Content-Location"] = entry.Location.AbsoluteUri;
WebOperationContext.Current.OutgoingResponse.ETag = etag;
WebOperationContext.Current.OutgoingResponse.SetStatusAsCreated(entry.Location);
return entry;
}
catch (ResourceNotFoundException rnfe)
{
WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound(rnfe.Message);
}
catch (InvalidContentTypeException icte)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotAcceptable;
WebOperationContext.Current.OutgoingResponse.StatusDescription = icte.Message;
}
catch (Exception ex)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
WebOperationContext.Current.OutgoingResponse.StatusDescription = ex.Message;
}
return null;
}

Personally I'd have done a little refactoring in and pulled out WebOperationContext.Current.OutgoingResponse into a variable, but you get the idea. I think there's some more opportunity for some larger, more profound refactorings as this method looks a lot like most of the others. CRUD (Create, Read, Update, Delete) code does tend to repeat.

I think Jarrett will be able to move all the try/catch and the caching work for eTags and what not into some helpers. The project site says the next step is to add some authentication and have that factored out into a module, and that's confirmed by his copious TODO comments.

I really enjoy reading code where someone, like Jarrett, has taken the time to actually put in TODO: comments. It's easier to get into the programmers head if you know where they are going, and TODOs also tell you where they've been. I can tell when I'm reading this that the project owner knows what's good and what's not, and from that, gauge the trajectory of the project.

image

Great stuff and I hope that we see more work like this in the .NET Open Source space around Atom and AtomPub. Why should you care? Perhaps you work for a company that has a content management system, or a sales catalog system where sales people want to edit project web pages. Why not put something like BlogSvc in front of it and let your sales folk use Windows Live Writer or some other AtomPub compliant editor? The possibilities are really endless.

WEIRD SIDE NOTE: I had a weird COM Interop Error when opening his "Web.csproj" - I'd get "System.Runtime.InteropServices.COMException." I opened the csproj in notepad and noticed two things. First, the IISUrl was set to his computer name, http://rocket, so I changed that to http://localhost. The other was that it said UseIIS="True" so I suspect that was a lame error message trying to tell me that I didn't have the IIS 6.0 compatibility extensions on my Vista system. I set it to UseIIS="False" and the project loaded fine.
CONFIRMED: I ran into this bug on Connect and I shall now yell about it internally.

It'll be interesting to see how BlogSvc and ADO Data Services in 3.5 SP1 intersect. BTW: You can learn more about ADO Data Services by watching the How Do I videos on MSDN. (Yes, the video player sucks, but you can download the WMVs.)

Technorati Tags: ,,

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 126 - Chat with John Resig, Creator of jQuery

August 15, '08 Comments [9] Posted in ASP.NET | Javascript | Podcast
Sponsored By

image My one-hundred-and-twenty-sixth podcast is up. I got to talk to John Resig the creator of jQuery. We talk about about how he developed jQuery, how it performs, and where he thinks it's headed.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Telerik's new stuff is pretty sweet, check out the ONLINE DEMO of their new ASP.NET AJAX suite. RadGrid handles sorting, filtering, and paging of hundreds of thousands of records in milliseconds, and the RadEditor loads up to 4 times faster and the navigation controls now support binding to web services on the client.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hidden Gems - Not the same old 3.5 SP1 post

August 13, '08 Comments [32] Posted in ASP.NET | ASP.NET Dynamic Data | ASP.NET MVC | Windows Client | WPF
Sponsored By

Folks were hassling me in the comments for not posting the picosecond that .NET 3.5 SP1 came out (or, as I like to call it, .NET 3.6 - although the bosses really don't like that).

First, the obvious stuff.

Should I fear this release?

I wouldn't. The SP1 Framework is full of goodness. The VS Installer is slow (it was for me) but I just shut everything down, ran it, and was patient. It's POSSIBLE. It's way better than the beta installer was. There's a metric buttload of little VS fixes and tweaks that make the IDE a more pleasant place to spend your day. ScottGu lists a bunch of new stuff, like JavaScript intellisense, formatting, editor performance improvements, and on and on.

If you want to see some crazy interesting statistics, go check out Patrick Smacchia's updated 3.5 SP1 Changes Overview.

You can get it here:

If you've ever installed anything wacky or beta, be sure to run the important Preparation Tool and also R'ingT*M.

Now, why should I bother?

What's it got for ASP.NET?

There are lots of details here http://www.asp.net/downloads/3.5-sp1 including stuff on things we used to call ASP.NET 3.5 Extensions (in case you were wondering where all that went.)

ASP.NET Dynamic Data: This is now included in the .NET Framework 3.5 Service Pack 1 release. You can find further information on ASP.NET Dynamic Data here as well as instructions on how to convert applications written using the ASP.NET 3.5 Extensions December 2007 CTP in the readme. Piles of Dynamic Data videos here.

ASP.NET MVC: Nope! MVC has always been a separate release. Check out Phil Haack's blog for details!

ASP.NET AJAX browser history: This is now included in the .NET Framework 3.5 Service Pack 1 release. You can find details of how to convert applications written using the ASP.NET 3.5 Extensions December 2007 CTP in the readme. Check out the Video on AJAX Browser History.

ADO Data Services - It's RESTful! RESTy! A POX on your data! It's AtomPubtastic. Go check out Pablo's most excellent ADO.NET Data Services ("Project Astoria") videos from Mix.

ADO.NET Entity Framework: The ADO.NET Entity Framework is now included in the .NET Framework 3.5 Service Pack 1 release. You can find the documentation for the ADO.NET Entity Framework here. There's also an EntityDataSource.

ASP.NET controls for Silverlight: These ASP.NET Web server controls make it easier to use Silverlight in ASP.NET Web applications. These controls are now included in the Microsoft Silverlight 2 Software Development Kit.

Not to mention other new features like AJAX Script Combining (check the AJAX Script Combining video by Bertrand) and find out "What's the big deal with Script Combining?"

What's it got for Fat Chubby Smart Rubenesque Clients?

Bunch of new SP1 stuff on the client side, and I fully intend to have BabySmash exploit the new stuff as much as possible.

One of the cooler things is the new 3.5 Client Profile bootstrapper. This means I can get a Windows XP SP2 machine with no .NET Framework installed up and running with the 3.5 Client (WinForms, WPF, etc) assemblies in just 26megs with a 200k bootstrapper. I'm going to blog on how to do this, and use BabySmash as a guinea pig soon.

  • Immediate Responsiveness: Bootstrapper is small (200K) to enable the fastest possible response. After the security prompts, the user immediately is presented with the EULA.
  • 3 Clicks: One for the application, installing certificates, and the EULA. For ClickOnce, the user clicks accept on the EULA and the application automatically launches once setup is complete.
  • Size and Speed: With a typical broadband connection, setup will take ~6 minutes or less.
  • Faster launch time: Bunch of NGen and memory layout and CLR improvements.
  • FireFox ClickOnce and XBAP support. Finally!

What about ASP.NET MVC?

There is likely some confusion around MVC as a few people expected ASP.NET MVC to ship in SP1. This is probably because MVC was included in 3.5 "Extensions Preview." However, the plan was always to ship in Q4CY08.

(That date is marketing speak, I've just learned. I tell people what Eilon told me - it'll ship in a month ending in "-ber." Possible "March-ber" but also maybe "next June-ber.")

Anyway, Phil has always said that MVC is on its own schedule and will ship when its done. Possibly when Duke Nukem Forever ships.

What else is new? What about ASP.NET itself?

Here's the unsung heroes. Scott Galloway and the ASP.NET will do some articles in exquisite (I hope) detail on http://www.asp.net soon on all the subtle good fixes in ASP.NET, so watch for those.

Here's some details on a few niceties for people who like their URLs and Forms a certain way.

  • RenderAllHiddenFieldsAtTopOfForm - In versions of ASP.NET earlier than the .NET Framework 3.5 SP1, ASP.NET renders some hidden fields (for example, __VIEWSTATE) at the top of the form. Other hidden fields (for example, __EVENTVALIDATION) are rendered near the bottom of the form, just before the closing </div> tag. By default, in ASP.NET 3.5 SP1, all system-generated hidden fields are rendered at the top of the page. This makes sure that the information in these fields is sent to the server even if a postback is performed before the page has finished loading. If RenderAllHiddenFieldsAtTopOfForm is set to false, performing a postback before the page has finished loading can cause an "Invalid postback or callback argument" error.

    This is a nice, but subtle fix. Basically if you tried to do a postback (AJAX or otherwise) before the whole page was loaded and one of the hidden fields like __EVENTTARGET wasn't loaded yet because it was rendering at the bottom of the page, you'd be in a pickle. And you'd get a validation error on post. Now you can set this to true and move those hidden fields to just below the <form>.
  • HtmlForm.Action is now settable - Again, subtle, but very cool.  I like to use URL rewriting a lot and want my <form action=""> to be a certain way. Now I can set it manually without fooling around with RegEx's and messing with the whole response.
  • RedirectMode for CustomErrors - Also nice for URL redirects. If you set the redirectMode on <customErrors/> in web.config to "responseRewrite" you can avoid a redirect to a custom error page and leave the URL in the browser untouched.

A few more advanced improvements:

  • There's a new overload of System.Web.Caching.Cache.Insert() and a new CacheItemUpdateCallback. Thomas Marquardt has more on this in detail. Now you can get notified when a cache item is invalid and you get an opportunity to generate a replacement. This means you actually get warned BEFORE the item is yanked.
  • New RemapHandler method on HttpContext lets you swap in your own IHttpHandler mid-request as long as you do it before MapRequestHandler has been called.
  • New throttling option under IIS7 using aspnet.config. You can set MaxConcurrentRequestsPerCpu or MaxConcurrentThreadsPerCpu. For example, if you had a number of high-latency calls that were tying things up, you could use change the Concurrent Threads setting to throttle more logically than Concurrent Requests.
  • Now Response.Flush is safe reliable to call from a background thread. Before you could wreck havoc if you called Flush from the the background in an AJAX app, but no longer!
  • Remember that System.Web.Routing has been brought over from MVC world and is a core part of ASP.NET now. You can use ASP.NET Routing as you like and there's a fine writeup on Routing here. How is Routing different from URL Rewriting?

    ASP.NET routing differs from other URL rewriting schemes. URL rewriting processes incoming requests by actually changing the URL before it sends the request to the Web page. For example, an application that uses URL rewriting might change a URL from /Products/Widgets/ to /Products.aspx?id=4. Also, URL rewriting typically does not have an API for creating URLs that are based on your patterns. In URL rewriting, if you change a URL pattern, you must manually update all hyperlinks that contain the original URL.

    With ASP.NET routing, the URL is not changed when an incoming request is handled, because routing can extract values from the URL. When you have to create a URL, you pass parameter values into a method that generates the URL for you. To change the URL pattern, you change it in one location, and all the links that you create in the application that are based on that pattern will automatically use the new pattern.

If any of these small but important fixes make you smile, thank Stefan Schackow and the ASP.NET team. If you ever see them, give them a hug, it'll make them very uncomfortable. There are more fixes, and I hope ScottGal expounds on them soon at http://www.asp.net

What about Connected Services?

On the services side, Sam Gentile points out a bunch of new WCF features in 3.5 SP1 like:

  • Improvements in writing REST based services ranging from easily supporting ServiceDocuments publication and consumption to providing greater control and usability of UriTemplate with new syntax. AtomPub support in a new Object Model.
  • DataContract Serializer gets way easier by relaxing/removing the ned for [DataContract] and [DataMember] on types. It's POCO (Plain Ol' CLR Object) time, people.
  • More interoperable object references in the serialization format, which means WCF gets along better with Java.
  • New Hosting Wizard when making new WCF Services.
  • Better Partial Trust behavior, particularly when tracing/logging.
  • Support for ADO.NET Entity Framework types in WCF contracts.
  • WCF Templates for consuming services from Silverlight.
  • Scalability increases of 5X-10X (oy!) for WCF services hosted in IIS7-integrated pipeline mode.
  • The Workflow Designer is has a number of performance improvements and is generally quicker.

Related Posts

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.