Scott Hanselman

Extending NerdDinner: Adding MEF and plugins to ASP.NET MVC

May 20, 2010 Comment on this post [16] Posted in ASP.NET | ASP.NET MVC | NerdDinner | Open Source | Source Code
Sponsored By

The original NerdDinner Sample was very simple. Two samples, simple, in fact. Perhaps it's the new Northwind, as it's a good way to start working with ASP.NET MVC. However, it's not a perfect sample or an idealized example on how to do many things that users want to do.

Fortunately, there's been lots of cool folks in the community who have "forked" NerdDinner and done interesting stuff with it. Each of these samples is usually focused on a specific scenario, so they won't necessarily be merged with the trunk, but they are educational nonetheless.

Jon Galloway and I have also added a few things to NerdDinner, taking it in a more social direction, as Jon's MVC Music Store today is a better "getting started" sample for ASP.NET MVC 2. We'll be doing a series of posts on the interesting things the community has added to NerdDinner as well as some of the ones Jon and I added and presented at Mix a few months back. Soon Jon and I will release an updated NerdDinner v2 on CodePlex (although it's been in the source code tab for weeks) with lots of fixes, new features. We'll also add many of these "one off" samples as well and host them on CodePlex.

I spoke to Microsoft Engineer Hamilton Verissimo de Oliveira, aka "Hammett" (you likely know him from the Castle Project and Monorail) about making a NerdDinner sample that included MEF (Managed Extensibility Framework) since much of MEF is built into .NET 4 now. He was kind enough to do it, but I'm just blogging it now, so thanks to Hammett for his kindness and patience.

NerdDinner on MEF

MEF lives in System.ComponentModel.Composition. Hammett's done a number of interesting things it his sample, adding Microsoft.ComponentModel.Composition.Extensions and Microsoft.ComponentModel.Composition.Extensions.Web namespaces building in some nice extension methods for common techniques as well as and implementation of IControllerFactory and a derivation of HttpApplication.

MefControllerFactory

Remember MEF is about making applications easily composable. In this sample Hammett has created his own MefControllerFactory, replacing the default controller factory that comes with ASP.NET MVC. ASP.NET MVC makes it easy to change:

protected override void Application_Start()
{
base.Application_Start();

ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(base.ScopeManager));

RegisterRoutes(RouteTable.Routes);

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MobileCapableWebFormViewEngine());
}

Notice his controller factory has a ScopeManager. This is a web application, and some components might be at Application Scope (create them once and hang on) and some might be at Request scope (make a new one each request).

For controllers, he's effectively recreated the default behavior of the ASP.NET MVC's controller factory, but in doing it, has given us lots of ways we can jump in an change the behavior in exotic ways by overriding CreateRootCatalog in MefhttpApplication. It's default implementation looks in /bin:

protected virtual ComposablePartCatalog CreateRootCatalog()
{
return new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"));
}

As you probably know, ASP.NET MVC looks for classes via a convention. It looks for classes with the word "Controller" at the end that are also IController implmentations. Here's the MEF way to declare that convention using Microsoft.ComponentModel.Composition.Extensions. Note the use of scope.

[assembly: Discovery(typeof(Conventions))]

namespace NerdDinner
{
public class Conventions : ConventionDiscovery
{
public Conventions()
{
Add(PartRegistration.
Types(t => t.Name.EndsWith("Controller") && !t.IsAbstract).
Exporting((c, t) => c.
Contract(typeof (IController)).
Metadata("Name", t.Name.Substring(0, t.Name.Length - "controller".Length)).
Metadata("Mode", WebScopeMode.Request))
);
}
}
}

Pretty cool.

Controllers and their Needs

Whenever a more advanced programmer looks as the NerdDinner code they usually say they they really don't like this:

public DinnersController() : this(new DinnerRepository()) 
{
}

public DinnersController(IDinnerRepository repository)
{
dinnerRepository = repository;
}

The second constructor takes an IDinnerRepository, allowing us to make different implementations, but the default constructor says, "well, here's a concrete implementation if you don't give one." It's a slippery slope and by adding the default implementation I get to sidestep using dependency injection while making the controller testable, but I've tied my controller down with a direct dependency to the DinnerRepository. This is sometimes called "Poor Man's IoC" and many would say that this is a very poor man. That's a religious argument, but Hammett takes a stand by removing the default constructor.

public class DinnersController : Controller
{
private IDinnerRepository dinnerRepository;

public DinnersController(IDinnerRepository repository)
{
dinnerRepository = repository;
}
//...
}

So how does a DinnersController ever get an IDinnerRepository? The idea is that it's not the controllers job to worry about the how, it's only its job to want.

MEF is effectively a Dating Service for Components. Here DinnerRepository is saying it's available and it wants to meet someone who is also into "IDinnerRepository."

[Export(typeof(IDinnerRepository))]
public class DinnerRepository : NerdDinner.Models.IDinnerRepository {

That [Export] attribute is its way to saying, "I'm on the market. Matchmaker, make a match!" When MEF is asked for a Controller and it notices that it has no default constructor, as in our case, it looks at the available constructors and says, "Oh, DinnersController wants to meet someone too! I I think I know just your type." Then it creates a DinnerRepository and calls the DinnersController constructor passing it in. It injects the dependency.

Often you'll see the other components advertising their interest with an [Import] attribute, but that's not necessary in this example because all the Controllers were created via the MefControllerFactory. They don't need attributes, as they've already walked in the door of our dating service!

Other Services MEFified

Recently in a review of MVC Music Store Ayende (and others before him, as well) dissed on these line of code, which actually come with ASP.NET MVC 2 out of the box and weren't written for the sample. (Although they weren't changed)  Phil can speak to specific decisions as I wasn't involved, but many folks who are into dependency injection don't like this. This is effectively the same maneuver as shown above, written slightly differently.

public class AccountController : Controller 
{
public AccountController()
: this(null, null) {
}

public AccountController(IFormsAuthentication formsAuth, IMembershipService service)
{
FormsAuth = formsAuth ?? new FormsAuthenticationService();
MembershipService = service ?? new AccountMembershipService();
}
//...
}

Hammett's implementation just uses MEF, so:

public AccountController(IFormsAuthentication formsAuth, IMembershipService service)
{
FormsAuth = formsAuth;
MembershipService = service;
}

Again, the whole point is that the dependencies get figured out automatically, each one wearing the "I'm available for hooks ups" attributes of [Export(typeof(IFormsAuthentication))] and [Export(typeof(IMembershipService))] respectively.

All in all, MEF is a nice clean addition to an ASP.NET MVC app. Thanks to Hammett for his hard work!

Related Links

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Windows Server and Azure AppFabric virtual launch May 20th

May 19, 2010 Comment on this post [9] Posted in AppFabric
Sponsored By

Windows Server AppFabric I spent 7 years at a large e-Finance company working on an Application Server for Windows with a team of very smart folks. When we'd go and sell our application server/component container to banks, we'd have to say things like "Windows doesn't really have an actual App Server like jBoss or WebSphere, so we wrote our own." However, remember that we were in banking, not in appserver-writing, so I always thought this was cheesy. As Microsoft came out with different subsystems that did stuff we'd already done, we'd evaluate them and "refactor via subtraction," removing our stuff and moving over to the MS stuff when appropriate. Still, the lack of an AppServer was an irritant.

AppFabric is the Windows Application Server. For web applications, AppFabric gets you caching (remember "Velocity?") for scale as well as high-availability of in-memory data. That means replicated, in-memory distributed hashtables, effectively, with PowerShell administration. I showed this at TechEd in Dubai, it's pretty cool.

For composite apps, on the business tier, AppFabic gets you services to support Windows Workflow and Windows Communication Foundation (WCF) apps. That means, workflows and web services get supporting services for scale. (remember "Dublin?"). For all apps, you get nice instrumentation in MMC that will live alongside your IIS7 management snapins, so you don't have to run around in multiple places to manage apps.

Most of these links, training and sample, show Beta 2 today, but will be updated soon to the final bits, I hear. There's lot more coming, and I'll do my best to collect the info in as clear a way as possible.

Related Links

If you're building BIG stuff of scale, as I did for 15+ years, AppFabric should prove pretty useful. I'm going to spend some time digging into it and I'll try to get the inside scoop from the team in the coming months. I'm also going to look into how well this all plays with Open Source libraries and subsystems.

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Most Common ASP.NET Support issues - Reporting from deep inside Microsoft Developer Support

May 19, 2010 Comment on this post [21] Posted in ASP.NET | Bugs
Sponsored By

Microsoft Developer Support or ("CSS" - Customer Support Services) is where you're sent within Microsoft when you've got problems. They see the most interesting bugs, thousands of issues and edge cases and collect piles of data. They report this data back to the ASP.NET team (and other teams) for product planning. Dwaine Gilmer, Principal Escalation Engineer, and I thought it would be interesting to get some of that good internal information out to you, Dear Reader. With all those cases and all the projects, there's basically two top things that cause trouble in production ASP.NET web sites. Long story short, Debug Mode and Anti-Virus software.

Thanks to Dwaine Gilmer, Doug Stewart and Finbar Ryan for their help on this post! It's all them!

#1 Issue - Configuration

Seems the #1 issue in support for problems with ASP.NET 2.x and 3.x is configuration.

Symptoms

Notes

  • OOM
  • Performance
  • High memory
  • Hangs
  • Deadlocks

There are more debug=true cases than there should be.

People continue to deploy debug versions of their sites to production. I talked about how to automatically transform your web.config and change it to a release version in my Mix talk on Web Deployment Made Awesome. If you want to save yourself a headache, release with debug=false.

Additionally, if you leave debug=true on individual pages, note that this will override the application level setting.

Here's why debug="true" is bad. Seriously, we're not kidding.

  • Overrides request execution timeout making it effectively infinite
  • Disables both page and JIT compiler optimizations
  • In 1.1, leads to excessive memory usage by the CLR for debug information tracking
  • In 1.1, turns off batch compilation of dynamic pages, leading to 1 assembly per page.
  • For VB.NET code, leads to excessive usage of WeakReferences (used for edit and continue support).

An important note: Contrary to what is sometimes believed, setting retail="true" in a <deployment/> element is not a direct antidote to having debug="true"!

#2 Issue - Problems with an External (non-ASP.NET) Root Cause

Sometimes when you're having trouble with an ASP.NET site, the problem turns out to not be ASP.NET itself. Here's the top three issues and their causes. This category are for cases that were concluded because of external reasons and are outside of the control of support to directly affect. The sub categories are 3rd party software, Anti-virus software, Hardware, Virus attacks, DOS attacks, etc.

If you've ever run a production website you know there's always that argument about whether to run anti-virus software in production. It's not like anyone's emailing viruses and saving them to production web servers, but you want to be careful. Sometimes IT or security insists on it. However, this means you'll have software that is not your website software trying to access files at the same time your site is trying to access them.

Here's the essence as a bulleted list

  • Concurrency while under pressure: This causes problems in big software. Make sure your anti-virus software is configure appropriately and that you're aware of which processes are accessing which files, as well as how, why and when
  • Profile your applications: .NET and the Web are not black boxes. You can see what's happening if you look. Know what bytes are going out the wire. Know who is accessing the disk. Measure twice, cut once, they say? I say measure a dozen times. You'd be surprised how often folks put an app in production and they've never once profiled it.
  • Anti-Virus Software: It can't be emphasized enough that site owners should ensure they are running the latest AV engine and definitions from their chosen anti-malware vendor. They've see folks hitting hangs due to flakey AV drivers that are over two years out of date.  Another point about AV software is that it is not just about old-school AV scanning of file access. Many products now do low level monitoring of port activity, script activity within processes and memory allocation activity and do not always do these things 100% correctly. Stay up to date!
  • Know where you're calling out to: Also, connection to remote endpoints: calling web services, accessing file systems etc. All of this can slow you down if you're not paying attention. Is your DNS correct? Did you add your external hosts to a hosts file to remove DNS latency? 
  • processModel autoconfig=true: This is in machine.config and folks always mess with it. Don't assume that you know better than the defaults. Everyone wants to change the defaults, add threads, remove threads, change the way the pool works because they think their textboxes-over-data application is special. Chances are it's not, and you'd be surprised how often people will spend days on the phone with support and discover that the defaults were fine and they had changed them long ago and forgotten. Know what you've changed away from the defaults, and know why. Don't program by coincidence.

...and here's the table of details:

Issue

Product

Description

Symptoms

Notes

Anti-virus software

All

Anti-virus software is installed onto Servers and causes all kinds of problems. 

  • Application restarting
  • Slow performance
  • Session variable are null
  • Cannot install hotfix
  • Intermittent time outs
  • High memory
  • Session lost
  • IDE Hangs
  • Deadlocks

This consists of all AV software reported by our customers. All cases do not report the AV software that is being used so the manufacturer is not always known. 

KB821438, KB248013, KB295375, KB817442

3rd party Vendors

All

This is a category of cases where the failure was due to a 3rd party manufacturer.

  • Crash
  • 100% CPU
  • High memory
  • Framework errors
  • Hang

The top culprits are 3rd party database systems, and 3rd party internet access management systems.

Microsoft component

All

Microsoft software

  • Intermittent time outs
  • High memory
  • Deadlocks
  • 100% CPU
  • Crash

Design issues that cause performance issues like sprocs, deadlocks, etc. Profile your applications and the database! (Pro tip: select * from authors doesn't scale.) Pair up DBAs and programmers and profile from end to end.

Spread the word! What kinds of common issues do YOU run into when running production sites, Dear Reader?

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Make the Visual Studio 2010 IDE colors look like Visual Studio 2008

May 14, 2010 Comment on this post [14] Posted in VS2010
Sponsored By

 Theme MenuPersonally, I like the new Visual Studio 2010 IDE colors but I got this comment recently from a helpful reader:

Why did the default colour theme for VS 2010 have to be so hideously ugly? Why put all that work into making the most advanced IDE ever, and then present it with a look that screams "we didn't care?" ... An official facelift patch would be nice, if just the 2008 look was applied to 2010.

Well, each to is own. Just like Henry Ford said, "You can have any color you want as long as it's black." Seriously, though, you can change the colors if it makes you happy. Folks feel strongly about their colors, like our friend above.

There's a free Visual Studio Color Theme Editor by Matthew Johnson that you can download and modify the VS IDE theme however you like. Once you've installed it (it's a VSIX - an extension to VS2010 - not an MSI, so don't be scared) there will be a new menu in VS called "theme."

Here's the built in themes. Remember these are VS themes, not Windows themes, so they won't affect Windows colors. Also, this is changing the colors of the IDE itself, not the text editor. You can choose your text styles at http://studiostyles.info.

Windows XP Silver

MvcMusicStore - Microsoft Visual Studio (5)

Windows Classic

MvcMusicStore - Microsoft Visual Studio (9)

Windows XP Emerald

MvcMusicStore - Microsoft Visual Studio (7)

Windows XP Autumn

 MvcMusicStore - Microsoft Visual Studio (6)

Windows XP Olive

MvcMusicStore - Microsoft Visual Studio (4) 

Windows XP Blue

MvcMusicStore - Microsoft Visual Studio (3)

Windows Aero

MvcMusicStore - Microsoft Visual Studio (2)

Windows XP Blue

 MvcMusicStore - Microsoft Visual Studio

Default Visual Studio 2010 Theme

 MvcMusicStore - Microsoft Visual Studio (8)

Have fun! You can make your own themes as well and import/export them. Enjoy.

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

30 Tips for Successful Communication as a Remote Worker

May 14, 2010 Comment on this post [17] Posted in Remote Work
Sponsored By

2715599454_ca105ab726_mAs a Remote Worker I'm always looking for tips and tricks and checklists to make my, ahem, remote working life easier. I've made a cheap Wide Angle Lens so I could better see my co-workers, created a robot cart so they won't forget me, tested 4G cards so I can be online anywhere, switched to Hi-Def Video Cameras for web chat, written articles on how to Collaborate with Remote Employees and Phil Haack and I made the HanselPortal, for virtual camaraderie.

Recently I write up my "Good Better Best" webcam equipment list, so you can look amazing with a RingLight and a quality camera.

Show consideration

  • Set up calls at mutually workable hours. Avoid blocking calendars with local meetings during shared hours. Fridays are often a poor choice.
  • Start on time. Leaders should set up the bridge or Zoom/Teams/Meeting before the call starts. Attendees should always show up on time.
  • If you can't make it, cancel or decline least 18 hours in advance. Changing your plans to attend a non-existent meeting is very frustrating. Think carefully if the recipient will see your cancellation in time (they may be asleep).
  • Assume the best. If the other team isn't meeting your expectations, it's probably because of a lack of awareness or a misunderstanding—not incompetence. Clarify and confirm before drawing conclusions or judging.

Use the right tools

  • Choose the right tool. Skype is great for 1-1s and small group meetings. Teams is usually better for large group meetings.
  • Use video.  Seeing faces increases the quality of the communication. It also helps create focus, preventing people from getting distracted, having side conversations, checking their email, etc.
  • In a group, use a Camera with a wide angle. Mount it so the ROOM can be seen.  As well as enabling video, the noise-cancelling mics it has are excellent.  Make sure all your meeting rooms have one, including the satellite mics.
  • On your own, use a headset.  The sound quality for both parties is far superior.
  • Don't use your laptop microphone. Laptop microphones are poor quality and pick up noise from your laptop's fan, disk, and keyboard. Use the mic on your webcam or, better yet, an external mic.
  • Be a black-belt with the tools. Make sure you can set up and join meetings quickly so that they start on time. Learn all the available features. Set up time to sit with your local team to practice and explore.

Be Heard and Understood

  • Speak clearly and slowly. The connections aren't always clear.
  • Be precise and concise. Help to keep the meeting short and productive.
  • Speak one at a time, otherwise no-one can be heard.
  • Ask for confirmation that the callers heard everything clearly.
  • Sit near the microphone, especially if your voice is soft.
  • Ask for comments. It's hard to break into the conversation over the phone.
  • Avoid jargon and culture-specific phrases. English is not the first language of many people on our teams, and can also vary greatly across cultures.
  • Meet face to face from time to time.  Meeting in person builds your knowledge of each other's mannerisms and communication style.  Subsequent remote communications are much richer and misunderstandings rarer as a result.

Make meetings effective

  • Pick the right forum. Use meetings rather than long email threads to discuss complex issues. For small meetings, it is often better if everyone is in their own office rather than using a meeting room—this promotes equality between local and remote team members.
  • Share the context and goals. Shared context is critical to clear communication. There are often a lot of assumptions you know in a particular location based on side-conversations, etc.
  • Share a deck. It's much easier to follow the conversation if everyone is looking at the same thing. Even if you are sharing via Zoom or Teams, send the deck or a link to the deck by email well in advance (home connections can be slow) and call out each slide.
  • Send minutes promptly. After every meeting, send minutes documenting all decisions and including clear actions and owners. Avoid cryptic or overly-concise notes—imagine them being read or reported out by someone who wasn't there, six months later.
  • Record and share brown bags. Brown bags are often at unsociable hours. Recording and sharing helps partner teams as well as your own.

Make Email Work

  • Be clear and precise. It's very easy to misinterpret email, especially across cultures and languages. Re-read your emails before sending.
  • Document everything. Document all decisions - if it's not recorded in email, it didn't happen.
  • Share everything. Use email to share face-to-face hallway, office, lunchtime or post-meeting conversations.
  • Be inclusive. Leave time for other sites to read and reply before closing the issue (as appropriate).
  • Set up inclusive DLs. Having all stakeholders on the appropriate distribution lists is the easiest way to keep from forgetting other sites. Don't hide DL membership.
  • Answer all questions asked. Incomplete answers lead to frustration and wasted time.
  • Avoid unnecessary questions. Ask yourself ‘is it really worth a 24-hour turn-around to answer this question? Can I answer it myself, or ask someone local?' Don't block an important thread with a trivial question.

Related Links

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

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