Nik's Technology Blog

Travels through programming, networks, and computers

Ambiguous DLLs

We’ve just been testing an upgrade our CMS and come across a few problems concerning newer versions of assemblies interfering with older versions stored in the GAC.

The solution is to use a binding redirect in Web.Config to tell the framework to use the latest version.  For more info see Redirecting Assembly Versions.

   1: <runtime>
   2:   <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
   3:     <dependentAssembly>
   4:       <assemblyIdentity name="Immediacy.Web" publicKeyToken="b35b2a186fcebe46"/>
   5:       <bindingRedirect oldVersion="6.1.0.0" newVersion="6.2.0.0"/>
   6:     </dependentAssembly>
   7:   </assemblyBinding>
   8: </runtime>

To get the publicKeyToken for the DLL you need to open a Visual Studio command prompt and navigate to the folder containing the DLL and type:

SN –T assemblyname.dll

This will give you the publicKeyToken to put in the assembly identity.

Alternatively you could remove the old version of the DLL from the GAC by using this command with the Global Assembly Cache Tool

gacutil /u Immediacy.Web, Version=6.1.0.0, Culture="en",PublicKeyToken=b35b2a186fcebe46

No defining declaration found for implementing OnValidate(System.Data.Linq.ChangeAction)

If you happen to be getting an error message like the one below, then read on.

Error    1    No defining declaration found for implementing declaration of partial method 'mvcCMS.Models.WebPage.OnValidate(System.Data.Linq.ChangeAction)'    C:\mvcCMS\Models\WebPage.cs    28    22    mvcCMS


I'm using LINQ to SQL designer in Visual Studio to create a database schema and I'm using a partial class to extend the code generated by the designer.

In the example below I am using the pattern used by NerdDinner.com to add business rules/validation to the model classes LINQ to SQL built based on my database schema.

namespace mvcCMS.Models
{
    public partial class WebPage
    {
        public bool IsValid
        {
            get { return (GetRuleViolations().Count() == 0); }
        }
        public IEnumerable<RuleViolation> GetRuleViolations()
        {
            if (String.IsNullOrEmpty(Title))
                yield return new RuleViolation("Title is required", "Title");
            if (String.IsNullOrEmpty(Text))
                yield return new RuleViolation("Web copy is required", "Text");

            yield break;
        }
        partial void OnValidate(ChangeAction action)
        {
            if (!IsValid)
                throw new ApplicationException("Rule violations prevent saving");
        }
    }
}

Where OnValidate() is a partial method LINQ to SQL provides which enables us to be notified when the object is about to be persisted to the database, so we can check all our business rules have been met before the object is flushed to the database.

An empty OnValidate() method is part of the designer generated code for your data class located in the #region Extensibility Method Definitions and it seems that these Extensibility Method Definitions only get added to the designer code when your tables have primary keys.

When a table is dragged onto the Object Relational Designer in Visual Studio the classes that are generated will only implement INotifyPropertyChanging and INotifyPropertyChanged if your tables have primary keys.  If the classes don't implement these interfaces the code won't implement the OnValidate() method, and if the OnValidate() method doesn't exist your partial class won't compile.

The Solution

The solution is simple.  Add a primary key to your database table, delete the associated data class from the Object Relational Designer and then drag the database table from Server Explorer back onto the Object Relational Designer surface.

You should then find the designer generated code now implements INotifyPropertyChanging and INotifyPropertyChanged and the class contains a definition for OnValidate() in the #region Extensibility Method Definitions.  Your code should now compile.

Setting Up ASP.NET MVC with NUnit for Visual Studio 2008 Standard Edition &amp; Visual Web Developer Express 2008

I've just spent my lunch hour downloading and installing ASP.NET MVC.  I also downloaded the sample chapter from Professional ASP.NET MVC 1.0 (large PDF) which walks through the development of NerdDinner.com.  I began to create a test ASP.NET MVC project on Visual Studio 2008 Standard.

One of the main positives of ASP.NET MVC is that Test Driven Development is so much easier than with ASP.NET Webforms.

I soon realised when I created my first ASP.NET MVC project however that unless you have Visual Studio Professional or higher you don't get Visual Studio test Unit Framework, which means that to create a test project, you first need to install another testing framework such as NUnit, and configure Visual Studio or Visual Web Developer 2008 to use it.

This is an extract from the book Professional ASP.NET MVC 1.0:

Note: The Visual Studio Unit Test Framework is only available with Visual Studio 2008 Professional and
higher versions). If you are using VS 2008 Standard Edition or Visual Web Developer 2008 Express you
will need to download and install the NUnit, MBUnit or XUnit extensions for ASP.NET MVC in order for
this dialog to be shown. The dialog will not display if there aren't any test frameworks installed.

I already had NUnit installed, so I began my search for an NUnit extension for ASP.NET MVC, which I found here. Updated NUnit Templates for ASP.Net MVC 1.0 RTM

After running installNUnit.cmd which created the registry entries required by Visual Studio, you need to make sure the registry entries created point to the compressed templates.

Note: If you are using Visual Web Developer 2008, this might be all you need to do.  Click on File > New Project and check to see if "Test" appears under "Project types" on the left-hand menu in the dialogue box.  If not carry on reading.

Copy the NUnit test templates from the downloaded directory (in your chosen .NET language) MvcApplication.NUnit.Tests.zip to the following folder on your machine:

%Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Test

or here for VWD 2008:

%Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\VWDExpress\ProjectTemplates\CSharp\Test

Then make sure the registry entry here:

HKEY_LOCAL_MACHINE\SOFTWARE\VisualStudio\9.0\MVC\TestProjectTemplates\NUnit\C#

or here for VWD 2008:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VWDExpress\9.0\MVC\TestProjectTemplates\NUnit\C#

Correctly points to the location of MvcApplication.NUnit.Tests.zip. e.g.

Path: CSharp\Test\

Template: MvcApplication.NUnit.Tests.zip

Then close all instances of Visual Studio and open up the command prompt and move to the following location:

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE>

and run the following command:

> devenv /setup

Once this has completed, you should find that when you create an ASP.NET MVC project, you will now get another pop-up menu asking you if you wish to create a unit test project for your application using NUnit.

Language Interoperability in the .NET Framework

.NET is a powerful framework which was built to allow cross-language support.  All .NET code is compiled to Intermediate Language (IL) whether you are developing in C#, VB.NET, J# or any other .NET language.  This means it is possible to build applications with modules written in different languages, because when the application is compiled it will all be compiled to a common language, IL.

This means a class written in one language can inherit from a class written in another language, or an object can directly call a method of another class written in another .NET language.  Visual Studio also allows you to step through all the different modules in the debugger.

To demonstrate the Language Interoperability in .NET, I'm going to call a VB.NET method from the code-behind page of a C# ASP.NET page.  This isn't something you would ordinarily want to do, but its an easy way to show the power of .NET.

In Visual Studio, right-click your website root in Solution Explorer and select add reference.  Scroll down the .NET tab until you find Microsoft.VisualBasic and click ok.

This will modify your Web.Config file by adding an assembly reference to Microsoft.VisualBasic to the assemblies list.

            <assemblies>
                <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
                <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Web.Extensions.Design, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
                <add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                <add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
      </assemblies>

To use the VB.NET language within your C# webform you need to add a using Microsoft.VisualBasic; statement at the top of your code-behind page.

In my demo example below I am going to use the VB.NET MonthName method of DateAndTime to get the current month's name and display it on my page using a ASP.NET label control.  The bold code below is VB.NET interspersed with C#.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.VisualBasic;

public partial class language_interop : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        int month = DateTime.Today.Month;
        string monthName = DateAndTime.MonthName(month, false);
        labelMonthName.Text = monthName;
    }
}

TargetInvocationException - Exception has been thrown by the target of an invocation

This exception isn't very useful because it's a general exception thrown when a method invoked through reflection throws an exception, took me a while to figure out what the issue was.  Even though I knew the page causing the error.

This exception was thrown by a ASP.NET web form which contained a GridView connected to an ObjectDataSource.

The ObjectDataSource references methods in a data access layer class.  These methods then call stored procedures in the MS SQL database. 

The code worked perfectly in my development environment.

I have the SQL database set up so that the database user ASP.NET uses only has rights to execute the stored procedures it needs to.  The database user cannot run commands against the tables directly, this way I limit the surface area of attack should my application have a weakness that could be exploited.

I double checked the stored procedures were all up-to-date, then double checked all the permissions on the stored procedures, and everything seemed in order, but I still kept getting the stack trace below in Event Viewer:


    Stack trace:    at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Web.UI.WebControls.ObjectDataSourceView.InvokeMethod(ObjectDataSourceMethod method, Boolean disposeInstance, Object& instance)
   at System.Web.UI.WebControls.ObjectDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments)
   at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
   at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
   at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
   at System.Web.UI.WebControls.GridView.DataBind()
   at System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound()
   at System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls()
   at System.Web.UI.Control.EnsureChildControls()
   at System.Web.UI.Control.PreRenderRecursiveInternal()
   at System.Web.UI.Control.PreRenderRecursiveInternal()
   at System.Web.UI.Control.PreRenderRecursiveInternal()
   at System.Web.UI.Control.PreRenderRecursiveInternal()
   at System.Web.UI.Control.PreRenderRecursiveInternal()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Custom event details:

I then decided to check the stored procedures.  Then it dawned on me that one of the stored procedures used EXEC sp_executesql, which requires the database user to have, in my case, SELECT permissions on the actual table itself.

Once I granted these permissions to the database user, the web form loaded correctly.

ASP.NET Content Disposition Problem in IE7

I've just spent quite a while debugging a problem with content disposition I was having with Internet Explorer 7, the code works fine in Firefox but causes this error message to occur in IE7.

"Internet Explorer cannot download xxx from xxx."

"Internet Explorer was not able to open this Internet site.  The requested site is either unavailable or cannot be found.  Please try again later."

content-disposition-error

This was my original snippet of C# code:

Response.Buffer = true;
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = docToDisplay.Type.ContentType.ToString();
Response.AddHeader("Content-Disposition", "attachment;filename=" + Server.UrlEncode(docToDisplay.FileName));
Response.Cache.SetCacheability(HttpCacheability.NoCache);

Response.BinaryWrite(docToDisplay.FileContent);
Response.End();
Response.Flush();
Response.Close();

Response.Cache.SetCacheability

I eventually figured out that the following line on code was causing the issue.

Response.Cache.SetCacheability(HttpCacheability.NoCache);

I then did a quick search for "Response.Cache.SetCacheability(HttpCacheability.NoCache);" and discovered another developer who have had the same Content-Disposition issue.  Unfortunately for me that page didn't get returned when I was searching for the Internet Explorer error message.

This was the response to the post by Microsoft Online Support:

"Yes, the exporting code you provided is standard one and after some further
testing, I think the problem is just caused by the httpheader set by
Response.Cache.SetCacheability(HttpCacheability.No Cache)
I just captured the http messages when setting and not setting the above
"NOCache" option and found that when the http response returned the
Cache-Control: no-cache
header. So we can also reproduce the problem when using the following code:
page_load...
{
Response.CacheControl = "no-cache";
ExportDataGrid(dgSheet,"test.xls");
}
IMO, this should be the clientside browser's behavior against "no-cache"
response with stream content other than the original text/html content. So
would you try avoid setting the CacheAbility or the "Cache-Control" header
to "no-cache" when you'd like to output custom binary file stream?
Thanks,
Steven Cheng
Microsoft Online Support"

After removing the Response.Cache.SetCacheability line the file downloads correctly in Internet Explorer.

Authenticate with MailEnable SMTP using ASP.NET 2.0

I've recently been trying to send emails using ASP.NET 2.0 on a web server which uses MailEnable. MailEnable had relaying locked down to avoid opening the server up to spammers, but I wasn't able to authenticate with MailEnable to relay emails to external domains.

I tested my code was working by temporarily checking the "Allow relay for local sender addresses" checkbox in the SMTP properties on MailEnable and my email was relayed successfully. However as soon as I uncheck this option I get this error message in the SMTP W3C logs:

503+This+mail+server+requires+authentication+when+attempting+to+send+to+a+non-local+e-mail+address.+Please+check+your+mail+client+settings+or+contact+your+administrator+to+verify+that+the+domain+or+address+is+defined+for+this+server.

I eventually got it working. I changed the authentication type from "MailEnable integrated authentication" to "Authenticate against the following username/password." then I supplied a username and password to MailEnable.
After restarting the SMTP service in MailEnable. I was able to relay emails using the following C# ASP.NET 2.0 code snippet...


using System.Net.Mail;

MailAddress source = new MailAddress("admin@localdomain.com", "Server");
MailAddress recipient = new MailAddress("external@mail.com", "External");

MailMessage enquiryMail = new MailMessage(source, recipient);
enquiryMail.Subject = "Test";
enquiryMail.Body = "Test content";
enquiryMail.IsBodyHtml = true;

SmtpClient smtpServer = new SmtpClient("mail.localdomain.com");
smtpServer.Credentials = new NetworkCredential("username", "password", "localdomain.com");
smtpServer.Send(enquiryMail);

Product Review: Train Signal's IIS Web Servers CBT Video Training

As an ASP.NET web developer, I think it's important to understand and know how to configure Microsoft's web server, Internet Information Services (IIS). Depending on the organisation you work for you may or may not get the opportunity to tinker with IIS, but this shouldn't stop you from learning the basics.

You could go out and buy a book on configuring IIS and then install IIS on your computer to practise what you've read, but thanks to the guys at Trainsignal.com who have kindly sent me some of their training videos, I've discovered a much easier way of learning.

Train Signal CD-ROM

Train Signal provides video training courses for Microsoft, Cisco and CompTIA certifications, including CCNA, A+, Network+.
I'll also be reviewing the Cisco CCNA training videos here soon.

Train Signal's IIS Web Server video training covers both IIS 5 and IIS6, and features topics including installing IIS, creating test websites, hosting more than one website using host headers, adding security, setting up an FTP server, and web server optimisation.

Train Signal CD-ROM menu

The course is taught by Scott Skinger, President and founder of Train Signal. Scott has many years of experience in the IT field, holds various IT certifications and is a competent instructor. The videos are easy to follow and Scott's narration is second to none.

Train Signal lab book sample

The series of videos are backed up with a written guide in the form of the lab book, which comes as a printable PDF on the CD ROM, this goes through the same steps featured in the videos and includes network diagrams like the one above to help you set-up your own lab.

Train Signal video player

If you want to get up to speed on a particular Microsoft product, obtain an IT certification or you don't like reading IT text books then I definitely recommend you give these training videos a try.

Course Contents in full:

Introduction
Lab Setup
Setting up the lab
Computer 1
Computer 2
Computer 3
Lab
Scenario
Installing IIS on Windows 2000 Server
Creating an HTML file
Hosting Ben & Brady's site
Configure DNS so Internet users can find your website
Testing the website from the client
Lab
Scenario
Creating a test website using an HTML file
Creating an additional website on the web server
Creating host headers
Configuring DNS for the second website
Test and view website from client
Assigning site operators
Adding security to a website
Test and view the website from a client
Lab
Scenario
Downloading and installing service packs and hot fixes
Setting NTFS permissions
Disabling Netbios over TCP/IP
Download and run The IIS lockdown tool from Microsoft
Enable and view logging

Product Review: uCertify PrepKit Exam Simulator

I was kindly sent a uCertify PrepKit for review back in December last year for the Microsoft C# .NET 2.0 Web-based Client Development exam (70-528). I'm looking to take the Microsoft MCTS .NET Framework 2.0 Web Applications certification this year, and needed an exam simulator and part of my study.

uCertify start-up logo

I've been so busy lately its been difficult to find the time to sit down and put the exam simulator through its paces. Anyhow I've spent a good few hours testing my .NET knowledge with this PrepKit to allow me to confidently evaluate it.

The PrepKit features a bunch of questions that closely follow the style of questions featured in the Microsoft exam, obviously the PrepKit does not contain real exam questions, but uCertify claim they are "realistic", and they are supposed to get you used to the kind of questions you should expect to see when you come to take the real exam.

uCertify PrepKit main menu

The tests in the PrepKit contain between 15 and 40 questions each and you’re given 120 minutes to complete each one, but I found that choosing a shorter time and reducing the amount of questions I needed to answer allowed me to spend more time using the PrepKit, because I don’t often have 2 hours of uninterrupted revision time.

There are two different modes to choose from before starting a test. Learn mode and Test mode, Learn mode allows you to get feedback on the current answer immediately whereas in Test mode you can only review the answers at the end of the practice test.

uCertify PrepKit test question page

When you complete a test you can review the questions and go back and look at any questions you may have answered incorrectly. You can also choose to re-take just the questions you got wrong. When you re-take the test the multiple choice answers change order to keep you on your toes!
During a test you can pause the timer to take a call, make a coffee etc, tag, print, review and bookmark questions.

uCertify PrepKit test history page

Every test you take with the PrepKit gets recorded in the Test History section, from here you can go back and review all the practice tests you've taken, review all the questions you got wrong, re-do the whole tests or re-do only the questions you got wrong.

Custom tests can also be created to turn your weaknesses, based on your test history or certain topics into your strengths.

Besides the practice tests the PrepKit contains study notes, quizzes and tips and flash cards to help assist you in understanding the topic.

MS Visual Web Developer 2008 Express Removes Support for Mobile Forms

I recently downloaded Microsoft's new Visual Web Developer 2008 Express Edition, which is a cut-down free version of Visual Studio aimed specifically at ASP.NET web developers. It supersedes the last version (VWD 2005) and adds new functionality.

I didn't remove the old version before installing, and in doing so noticed, and was able to verify (with screen shots below) that support for building mobile websites has been removed in the latest version, at least that's what appears to have happened!

Visual Web Developer 2005 - Add new item dialog box
Visual Web Developer 2005 - Add new item dialog box

Visual Web Developer 2008 - Add new item dialog box
Visual Web Developer 2008 - Add new item dialog box