Friday, 2 April 2010

RaiseBubbleEvent

I've just discovered the cool RaiseBubbleEvent that's provided within ASP.NET.  As the name suggests, it bubbles up event from the called methods, to the calling methods.  So, first, here's the code and afterwards I'll tell you why I needed to make use of it.
private void SomeCalledMethod()
{
/* Do some processing */
...
/* Now raise the bubble event up to the calling method. 
Whoever consumes this bubble event, they will know that it's telling them to Rebind.  Any phrase/word can be placed in here */
CommandEventArgs args = new CommandEventArgs("Rebind", String.Empty);
RaiseBubbleEvent(null, args);
}
protected
override bool OnBubbleEvent(object source, EventArgs args)
{
CommandEventArgs e = (CommandEventArgs)args;
if (e.CommandName == "Rebind")
{
//Rebind code goes here
}
return true;
}
The reason that I'm having to use this code is because I'm creating a web shop for a customer of ours and creating a shopping basket/cart.  The markup for the cart became quite long as I have 40 textboxes allowing the customer to type in part numbers directly, instead of browsing, so I thought I'd create a couple of user controls that could be reused in other projects.  However, when the user clicked on the "place all 40 items in the cart" button, it has to do some validation etc and then if successful, the shopping cart has to be displayed, but the logic to display the cart was in the basket.aspx page, and how was I going to inform this page that the shopping cart needed to be displayed.
So after a few suggestions from my colleagues, I tried using javascript and window.location.reload(), then history.go(0) and finally window.location.href=window.location.href.  Unfortunately the first two went into an endless loop reloading the page, asking did I really want to reload the page and the final one worked, but it just reloaded empty controls.  So I thought, okay, I'll use & set EnableViewState in the root for page, usercontrol and asp controls, but still no luck.  I then came across RaiseBubbleEvent and learnt of it's magical powers!  I wish I had been introduced to it years ago!
Anyway, happy bubbling!

Thursday, 1 April 2010

IIS 7 ISAPI Filters

Wow!  I have just spent nearly 4 hours trying to get a new web site up and running on Windows Server 2008, for one of our customers (as explained here in another article, but this time relating to having insufficient IIS permissions), all courtesy of the ISAPI filters and ISAPI extensions not being installed.
I knew where to install them on Vista, but it was Windows Server 2008 that was causing me the problems because they're not enabled in the same place. So, for those who need to know in Vista, follow the instructions immediately below. For those wanting to achieve it on Windows Server 2008, scroll down a little.
Vista
Go to: Control Panel -> Programs and Features -> Turn Windows features on and off (on the left hand side of the screen) and then navigate to what is shown below (you'll need at least ISAPI Extensions and ISAPI Filters ticked): 
Windows Server 2008
Go to: Control Panel -> Programs and Features -> Turn Windows features on and off (on the left hand side of the screen) and then choose the Roles value on the left -> followed by Web Server (IIS). Then on the right hand side, choose the Add Role Services. Then navigate to the Application Development and tick the ASP.NET, ISAPI Extensions & ISAPI Filters. As shown below: 

Wednesday, 31 March 2010

Failed to start monitoring changes to Global.asax

I was happily coding away the other day, when I came across the following error message when compiling my code in VS 2008: Failed to start monitoring changes to global.asax.  After a scratch of the head and another attempt at compiling, I still got the same message.  After a bit of digging around, I found the problem was in my web.config file and the offending line was:
After I removed this line, it compiled successfully.  Strange thing was, I have had this line in my web.config file for a long time and only now was the compiler working.  If anyone has any suggestions as to why, I'd be grateful to receive them.

Tuesday, 30 March 2010

I have been developing a WCF web service recently and in a previous post, I explain how to specify an EndPoint & binding in code.  That was a few weeks ago and it’s now time to make the web service run on the customer’s production server, however, to put a spanner in the works, not only did the customer want the web service to run over SSL, they created their own certificate, which forced a browser to show the message, “There is a problem with this website’s security certificate”.
I have two web services in this project, a traditional one (asmx) and the WCF.  So the certificate problem caused the asmx web service to fail too, until I found the following piece of code via Google, which I have extended ever so slightly to ensure that the certificate name is as we expected and whether it’s issue date is within bounds (I would attribute it to the author, but far too much water has passed under the bridge and I can’t remember who it was from).  The following code goes in the client (the caller) software:
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy()
{ }
public bool CheckValidationResult(ServicePoint sp, X509Certificate cert,
WebRequest req, int problem)
{
// This is out cert string issuer = ""; DateTime startDate = new DateTime(1753, 01, 01), endDate = new DateTime(1753, 01, 01); try {
startDate =
Convert.ToDateTime(cert.GetEffectiveDateString()); }
catch
{ }
try
{
endDate =
Convert.ToDateTime(cert.GetExpirationDateString()); }
catch
{ }
// Check that the issue and cert start & end date are valid
if (issuer == cert.Subject && startDate <= DateTime.Now && endDate >
DateTime.Now) return true; else
return false;
}
}
You can then issue the following piece of code which will call the CheckValidationRequest:
System.ServiceModel.EndpointAddress address = new System.ServiceModel.EndpointAddress(URL); WebServiceClient wService = new WebService.WebServiceClient(new System.ServiceModel.WSHttpBinding(), address); System.Net.ServicePointManager.CertificatePolicy = new WebServiceHelper.TrustAllCertificatePolicy();
Place a breakpoint in the CheckValidationRequest and you’ll see the request being issue.
So, this was perfect for the traditional asmx file, but for the life of me, I couldn’t get this to work for the WCF.  I Googled & Googled and found all sorts of weird & wonderful things that you could try and do to your config file to get the certificate to come through, but in the end, I found the following piece of code & config changes were required to get a self cert to work on a WCF web service:
The following line has been altered from above, to tell the TCP layer what type of transport is required:
WebService.WebServiceClient wService = new WebService.WebServiceClient(new System.ServiceModel.WSHttpBinding(System.ServiceModel.SecurityMode.Transport), address);
Notice how we need to tell the WSHttpBinding class, the transport mechanism.
Finally, in the web.config file of your WCF web service, you’ll need the following:
behaviors>  section --> <
bindings> <
wsHttpBinding> <
binding name="TransportSecurity"> <
security mode="Transport"> <
transport clientCredentialType="None"/>

security>
binding>
wsHttpBinding>
bindings>
system.serviceModel>


That’s it!  As I say, it took me hours to get find these tiny number of lines, but I was elated when I had! The errors that I was getting when running my code were: Could not find a base address that matches scheme http for this endpoint with binding WSHttpBinding ,or The requested service could not be activated

Monday, 29 March 2010

Error CS0433: type class exists in both dll location and dll location 2

I’ve just had the most annoying few days trying to identify why my Ajax web site worked on my dev & test machines, but it wouldn’t work on the live machine.  I have spent literally hours on this problem and I thought I’d share my solution even though there are other solutions which may help.
First off, I was receiving the following error on the live site when I tried to open any aspx page, even though the Ajax was only in one page:
“Error CS0433: type '' exists in both '' and ''” and I was also getting System.web.extensions.dll problems too.  Google was offering up a lot of results for both problems but they either talked about putting the System.web.extensions.dll in my Bin folder, which I did and made no difference but didn’t sit right with me anyway, or it said that you shouldn’t use an App_Code folder, which I do.
In the end, I opted for creating a new Ajax enabled project and then compare the web.config files, which was successful for me.  Below I’ve listed the two areas in my old web.config file which were wrong and then I’ve listed the new entries which replaced them.
1.  Old section
<configSections>
<sectionGroup name="microsoft.web" type="System.Web.Configuration.MicrosoftWebSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false"/>
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false"/>
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false"/>
sectionGroup>
sectionGroup>
sectionGroup>
configSections>
 
New section
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
sectionGroup>
sectionGroup>
sectionGroup>
configSections>
2.  Old section
<assemblies>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.Services.Client, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.Services.Design, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web.Extensions.Design, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
assemblies>
New section
<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"/>
assemblies>
That’s it!  And my code then started to work.  If any of the above helps just one person, I’ll be pleased, because this took an age to figure out.

Sunday, 28 March 2010

Content-Type-text-xml-charset-utf-8-was-not-supported-by-service-The-client-and-service-bindings-may-be-mismatched

I'm currently building a WCF web service and as we all know, the URL for the web service is stored in the web.config file, and I knew that when I came to deploy it to the live server, the binding would fail. Yes, I know I could publish the web service to the live server and then Add a reference in VStudio, but I like to put the test and live server URLs in the config file.
Anyway, I attempted to do the following in code, but I kept getting the error message: Content Type text/xml; charset=utf-8 was not supported by service The client and service bindings may be mismatched. And the code that caused the error was as follows:
System.ServiceModel.EndpointAddress address = new System.ServiceModel.EndpointAddress("");
InternalWebService.InternalWebServiceClient wService = new InternalWebService.InternalWebServiceClient(new System.ServiceModel.HttpBinding(), address);
Not exactly the most verbose error message in the world, so I tried a few things but they didn't work, so I started to look at the bindings, as this was perhaps the most likely culprit.  I looked in the web.config file and saw the following section:
<client>
<endpoint address=""
 
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMMDInternalWebService"
 
contract="MMDInternalWebService.IInternalWebService" name="WSHttpBinding_IInternalWebService">
So I scratch my head for a bit and started to think, hang on, wsHttpBinding, I’ve never seen that before.  So I used intellisense and found that if you type System.ServiceMode.wshttpbinding, a new class appears.  After a bit of googling, I found that HttpBinding, is used in Soap 1.1, but Soap 1.2 uses wshttpbinding().  Anyway, I wacked in the code and hey presto, the code started to call my web service.

Saturday, 27 March 2010

WinForms & the DataGridView

I was asked to do some WinForm programming the other day, which I haven't done for a couple of years now, because, as most of you are aware, I'm more a ASP.NET man with the occasional Win Mob thrown in.  And boy, was it good to be back!  I forgot how easy it was to do EVERYTHING!  You don't have to worry about CSS, state management, session vars...
Anyway, let me cut to the chase.  I wanted to use the DataGridView, populate it with data, and based on the data coming out of the DB, highlight certain cells, not rows, with the colour red and make the cell editable.  Well, as you know, the DataGridView is editable by default, so I was on a mission.  And the last requirement was to show only certain columns out of the entire data set, so I needed a way of creating the columns.  So, let me get to the point.  Below is how to create the columns:
dataGridView1.Columns.Add("Reason code(s)", "Reason code(s)");
dataGridView1.Columns.Add("Value0", "Value0");
dataGridView1.Columns.Add("Size 1", "Value1");
The first field is the column name, which I believe you can reference with something like: dataGridView1["ColumnName"], but don't quote me, and the second field is the header text for the column.  The final requirement for the columns, was to have a hidden column which would hold the unique key back in the DB.  Here you have to create a new DataGridView column and text box cell and set it properties, like so:

DataGridViewColumn newColl = new DataGridViewColumn();  
newColl.HeaderText = "";
newColl.Name = "NoteID";
newColl.DataPropertyName = "NoteID";
DataGridViewCell oCell = new DataGridViewTextBoxCell();
newColl.CellTemplate = oCell;
newColl.Width = 90;
dataGridView1.Columns.Add(newColl);
GetMobaOutuput();
Finally, I needed to highlight certain cells in red and make the editable and anything outside of the if, not editable.  Here goes:
dataGridView1.CurrentCell = dataGridView1.Rows[count].Cells[0];
dataGridView1.BeginEdit(true);
dataGridView1.Rows[count].Cells[0].ReadOnly = false;
dataGridView1.Rows[count].Cells[0].Style.Font = new Font("Verdana", 10, FontStyle.Bold);
dataGridView1.Rows[count].Cells[0].Style.BackColor = Color.Red;
You seem to need to call the BeginEdit method before you can alter the properties.  It was the ReadOnly property that took me a long time to find.  Setting it to false means that it's editable and vice versa.