Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

Two Form Tags in Asp.Net and My Work Around

Posted by Keith Elder | Posted in Asp.Net | Posted on 26-01-2008

4

I can’t remember the exact day but a few weeks ago around the start of the new year I changed out the site’s search to use Google’s search engine for AdSense.  Not thinking when I pasted the code I broke the comments and my contact form on the site for all Internet Explorer users.  The sad thing is I didn’t notice this until the other day when I started getting emails their was a problem.  For everyone that tried submitting comments and it not work I apologize.

The problem was when I pasted the Google AdSense Search code into my template it had a complete form tag thus giving me two form tags nested within each other.  After the paste I wound up with something like this.

<form runat="server">
    <!-- GOOGLE SEARCH -->
    <form method="get" action="someurl>
    </form>
</form>

With Asp.Net only one form tag is allowed within the body of a page and this is a topic that comes up a lot within Asp.Net forums and discussions.  There are ways around it like the one discussed on this article.  It isn’t an end of the world limitation just something you have to know or think about as you design your pages.

The way Google AdSense search works is when someone uses the search box in the top right of the site they are redirected to a page on my site that I control the layout on (this I like).  In my case it is called SearchResults.aspx.  Within that page there is JavaScript that takes the parameters via the URL and passes them into Google’s search specific for my site.  Results are then returned within the page within my site.  The end result is seamless to the end user and this cuts down on database work for my server.  But since I had two form tags in my html things were broke. 

Disclaimer:  The following is a hack that worked for my situation and may not work for all scenarios, use it at your own discretion.

After I figured out the problem I removed the Google start and end form tags.  Then I created a JavaScript function that took in an action and a method that would be used to replace the current one on the single form tag.  Here’s the JavaScript I added into the site.

<script type="text/javascript">
//<![CDATA[
function changeActionAndMethodOnFormAndSubmit(newAction, newMethod)
{
    var theForm = document.forms['Form1'];
    if (!theForm) {
        theForm = document.Form1;
    }
    theForm.action = newAction;
    theForm.method = newMethod;
    theForm.submit();
}
//]]>
</script>

Then within the Google code I added the function using the onclick event like this:

<input onclick="changeActionOnFormAndSubmit('http://keithelder.net/SearchResults.aspx', 'get')" type="submit">

After I uploaded the changes I typed something into the search and got results back.  Yeah.  I then tested in Firefox and IE7 and my hack worked.

 image

The only problem with this approach is there is a lot of other hidden form fields getting passed over in the URL.  Mostly view state and event argument stuff.  While not perfect this quick fix worked for my scenario which is good since I really didn’t want to mess with the main source code of the site.  The only reason I even posted this is in case someone needed a quick fix / work around as well.

How to Get Around WCF’s Lack of a Preview Web Page And Viewing WCF Messages

Posted by Keith Elder | Posted in Asp.Net, WCF, Web Services | Posted on 15-01-2008

10

I have a love hate relationship with Windows Communication Foundation.  I love it because the concepts of building a service are so simple.  I love the fact that I can expose the same service three different ways supporting different interoperability points within the business.  I also hate it because a there are so many ways to configure the service it can get daunting at times.  Configuration isn’t as bad as the built-in lack of ability to view messages.  WCF doesn’t provide a sample message page describing the SOAP messages for a request and response like the old ASMX services.  While this may not seem like a big deal there are systems I am having to interop with that can’t simply point to a WSDL and generate a proxy client from it (yes there still are some out there) and it is a problem.

The Problem

WCF offers a lot of binding options but when interopping with non .Net clients the basicHttpBinding is the obvious choice because it is the simplest.  If you can’t get that to work, good luck on the other ones.   Here is the quote from the MSDN pages about basicHttpBinding.

Represents a binding that a Windows Communication Foundation (WCF) service can use to configure and expose endpoints that are able to communicate with ASMX-based Web services and clients and other services that conform to the WS-I Basic Profile 1.1.

Changing bindings is really easy in WCF.  In VS2008, right click the config file in the project and select “Edit the WCF Configuration”.   The Microsoft Service Configuration Editor will then appear.  In the Services folder select the endpoint you want to change and in the binding section select the one you want.  This is the easy part.  The hard part is showing someone the message tied to the binding the service expects if they cannot generate a proxy within their language or platform from a WSDL.  In old ASMX services if the URL of the service was visited it would generate some nice pages for us automagically like this:

ASMX services display methods in service 

image

ASMX services when running locally could be easily tested with a prebuilt form

image

ASMX services provided a sample request and response XML message 

image

To the contrary WCF only provides .Net client info

 image

Yeah it is real useful isn’t it?

The Quick Fix

Why this is the case I have no good explanation.  One would at least think if the service was configured with the basicHttpBinding it would offer close to the same features of old.  Not the case though.  There is a big difference in the two obviously.  My first thought was to write a pluggin or some code that would provide the same functionality the old ASMX services do but I realized I had enough side projects to work on and I didn’t have the time.  Thus I was looking for a quick alternative to the problem.

The very first thing I did was open the Microsoft Service Configuration Editor and enable Message Logging in the Diagnostics folder.

image

With this enabled messages are written to the client or server.  It is a nice built-in feature that takes a lot more work with ASMX services.  With message logging enabled I ran my test service which added two numbers and then opened the message log using the SvcTraceViewer.exe.  SvcTraceViewer is part of the Windows SDK and does not ship with Visual Studio by the way.  Here are the messages generated in the log and viewed via the trace viewer.

image

This almost gave me the result I wanted.  Notice that it includes a lot of extra nodes and information.  The only nodes we care about start and end with <s:Envelope />.  This is our actual SOAP message.  If the trace option is enabled in WCF via diagnostics even more information is shown within this message.  I wanted to know the *exact* message that was going over the wire and back and I wanted to be able to look at it as I wrote my service or debugged it not having to launch a new tool.  Here is what I came up with.

The Programmatic Fix

WCF has tons of hooks and hooks mean extensibility.  My goal was simple.  I wanted to capture the request before it left my client and then capture the response message when it was received.  At first I thought this was going to be hard.  Then I stumbled upon an interface called IClientMessageInspector and my troubles were then over.

The first thing I did was create a class called MessageViewerInspector which implemented two interfaces.  The IClientMessageInspector and IEndPointBehavior.  Then I added two properties to my object which contained the request and response messages.  After that I implemented both interfaces with the object.  The IEndPointBehavior interface has four methods that need implementing but I only needed to use one which was ApplyClientBehavior.  In this method I added my MessageViewerInspector to the clientRuntime.   The IClientMessageInspector has two methods that need to be implemented which are the before and after.  This is where we get to see the messages before they leave the client and as soon as they come back.  Here is the complete object that will allow us to view our messages in WCF.

    /// <summary>
    /// Provides a custom behavior that allows a client to capture messages and log
    /// them or assist in debugging messages.
    /// </summary>
    public class MessageViewerInspector : IEndpointBehavior, IClientMessageInspector
    {
        
        #region Properties
        public string RequestMessage { get; set; }
        public string ResponseMessage { get; set; }
        #endregion

        #region IEndpointBehavior Members
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            // adds our inspector to the runtime
            clientRuntime.MessageInspectors.Add(this);
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {

        }

        public void Validate(ServiceEndpoint endpoint)
        {

        }
        #endregion

        #region IClientMessageInspector Members
        void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            this.ResponseMessage = reply.ToString();
        }

        object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
        {
            this.RequestMessage = request.ToString();
            return null;
        }
        #endregion
    }

All that was left was to add this custom inspector to the proxy as an endpoint behavior and we can see our messages coming and going.

Here is the code I added to my sample console application to test.

    class Program
    {
        static void Main(string[] args)
        {
            MessageViewerInspector inspector = new MessageViewerInspector();

            ServiceReference1.Service1Client proxy = new ConsoleApplication1.ServiceReference1.Service1Client();

            proxy.Endpoint.Behaviors.Add(inspector);
            proxy.AddTwoNumbers(12332, 12323);
            proxy.Close();

            Console.WriteLine("Request message:");
            Console.WriteLine(inspector.RequestMessage);
            Console.WriteLine(String.Empty);
            Console.WriteLine("Response message:");
            Console.WriteLine(inspector.ResponseMessage);
            Console.ReadLine();
        }
    }

As you can see above I created an instance of my new inspector and then added it to my proxy class.  After my request ran I simply printed the messages to the console as seen here.

image

The really nice thing with this approach that I liked is I now have the ability to view the request and response objects by simply placing a break point in either the after or before methods in the inspector class.  For example, here is a QuickWatch of the request object:

image

Now that the basic plumbing is in place we can do all sorts of things.  For example if an exception is thrown we could now log the specific message that was requested to cause our client to throw an exception.  Of course this also solves my original problem of being able to grab the specific messages sent and received and works with all bindings supported.  I hope this helps. 

Life With Visual Studio 2008

Posted by Keith Elder | Posted in .Net, Asp.Net | Posted on 01-08-2007

0

Visual Studio 2008 Beta 2 was recently released and it is now to the point where one could use it on a daily basis.  For me, there are a few things that are stopping me from jumping ship from VS2005 straight to VS2008 Beta 2.  A few of those revolve around the ability to install guidance packages such as the Web Service Software Factory for WCF and a few others.  

The good news is More Wally has already taken the plunge for those of us that are procrastinating and is reporting his ups and down with VS2008 in a series called Life With Visual Studio.  Keep that on the radar as he works through converting projects, etc. 

Cannot Invoke Workflows From Workflows Hosted in Asp.Net with Manual Scheduler

Posted by Keith Elder | Posted in Asp.Net, Web Services, Workflow Foundation | Posted on 30-07-2007

3

WasherAs you can see I’ve included my famous rusty washer on this post to denote a problem.  I was having a conversation with a team member about Workflow Foundation who was having a problem.  The problem was “Hey Keith, have you ever had workflows in Workflow Foundation invoke workflows?”.  Answer:  I  have not, but let’s talk about it, what’s the problem?

 My team member started explaining that they have a need for workflows to call other workflows.  Sounds simple enough since their is a pre-packaged activity in WF to do just this in the toolbox.

He further elaborated that when they invoke the workflows the workflow runtime dies.  At first I was perplexed, but then knowing they were hosting it in Asp.Net web service I asked which scheduler they were running.  He replied ManualWorkflowSchedulerService.  Ah ha!

The problem is a catch 22 and honestly I don’t have a solution for this.  The problem is that when hosting a workflow with the ManualWorkflowSchedulerService it cannot invoke other workflows.  I guess it makes sense since it cannot spawn a new thread, after all it is trying to process a new instance of a workflow on the same thread. (at least that is my theory) Is there a work around?  I don’t know.  Is it a problem, yeah!

To compound matters the only way to reliably host workflow foundation in Asp.Net service is with the ManualWorkflowSchedulerService.  Well, ok it isn’t the only way, but if there are problems using the default scheduler in Asp.Net.  Here is Paul Andrew’s post about a fix coming in WF where he explains the differences.

The DefaultWorkflowSchedulerService is the out-of-box Windows Workflow Foundation scheduler used by the runtime to execute workflow instances on new CPU threads.  These threads are leveraged from the.NET thread pool associated with the host application. This works well unless the workflow runtime is hosted in ASP.NET.  Because of the limited thread resource in the IIS server, we would be allocating an additional unnecessary thread to execute the workflow instance for every HTTP request that required workflow execution. The ManualWorkflowSchedulerService was developed to address this issue by allowing the thread that is processing the HTTP request to execute a workflow instance. Unfortunately in WF Beta 2.2 and prior, it didn’t handle the correct processing of timer events (i.e. delay activities).

When doing Asp.Net Web Services the only reliable way to return output parameters, catch exceptions, logging, handle faults, etc is to run the workflow on the same thread synchronously using the ManualWorkflowSchedulerService.  I’ve tried every which way I knew to get the default scheduler to work but couldn’t.  If you think about it, it makes sense since web services receive a message, then typically return a message.  With the default scheduler it is hard to bubble up exceptions properly so they can be logged or caught and handle gracefully in a service.

To test this theory I created a console workflow app and created two workflows with one calling the other like this.

image

I then wired up the ManualWorkflowSchedulerService in the Program.cs like this and run it.  It doesn’t run. If I comment out the manual scheduler and use the default, it works fine.

static void Main(string[] args)

        {

            try

            {

                using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())

                {

                    ManualWorkflowSchedulerService service = new ManualWorkflowSchedulerService(false);

                    workflowRuntime.AddService(service);

                    AutoResetEvent waitHandle = new AutoResetEvent(false);

                    workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };

                    workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)

                    {

                        Console.WriteLine(e.Exception.Message);

                        waitHandle.Set();

                    };

 

                    WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication1.Workflow1));

                    ManualWorkflowSchedulerService scheduler = workflowRuntime.GetService<ManualWorkflowSchedulerService>();

                    instance.Start();

                    scheduler.RunWorkflow(instance.InstanceId);

                    waitHandle.WaitOne();

                }

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.Message);

                Console.ReadLine();

            }

 

 So the catch 22 is I need to use the manual scheduler with Asp.Net Web Services but I can’t invoke other workflows if I do.  If I use the default scheduler, I can’t scale my service.  The “solution” we are going with right now for the work around is to host the service in WCF as a Windows Service outside of IIS.    The bad part of this is you can’t really scale this either.  That’s the nice thing about using IIS is it really is an app server.  Clustering and those things are widely available.  If you build your own windows service you lose all of that baked in functionality.  I think this is a HUGE rusty washer.   Anyone faced this challenge?  How did you solve it?  Am I off my rocker on this one?  Feedback would be appreciated.

UPDATE (8.28.2007)

One of the developers at work (Joe Brach) solved this problem since he was running into the same issue.  I thought I’d post his example of his fix since several people have been emailing me if I found a fix.  The “fix” is you create your own class that extends WorkflowRuntimeService.  Here is Joe’s fix:

    public class StartWorkFlowService: WorkflowRuntimeService

    {

        public Guid StartWorkflow(Type workflowType, Dictionary<string, object> inparms

        {

            //Get an instance of the runtime

            WorkflowRuntime wr = this.Runtime;

 

            //Create the type of Workflow

            WorkflowInstance wi = wr.CreateWorkflow(workflowType, inparms);

 

            //Start the WorkFlow

            wi.Start();

 

            //Get the Manual Workflow Service

            ManualWorkflowSchedulerService ss = wr.GetService<ManualWorkflowSchedulerService>();

 

            if (ss != null)

            {

                ss.RunWorkflow(wi.InstanceId);

            }

            return wi.InstanceId;

        }

    }

TechEd Day 2

Posted by Keith Elder | Posted in .Net, Asp.Net, Smart Clients, Web Services | Posted on 07-06-2007

0

It is day two of TechEd and my feet and legs are killing me.  My feet didn’t get a chance to rest after the four day whirlwind tour of Disney World.  I told my wife that I was going to have to go to TechEd just so I could rest 🙂  Here is day two’s activities.

Biztalk WCF Adapter

The first session I attended this morning was an overview of the WCF Adapter for Biztalk which is in the R2 release.  Don’t get your hopes up just yet because it isn’t available.  I was told it  wouldn’t be out until 3rd quarter.  The good thing is the WCF adapters bring a lot of cool things to the table.  I can’t remember all the reasons they gave but the one that a lot of people will use is the ability to do TCP binary messages to Biztalk I am sure.  Actually there are seven WCF adapters, one for each binding type.  The demo they showed was a message from a smart client being sent to Biztalk, and then Biztalk hitting SQL Server and then another service.  The orchestration had to route the message and handle the transaction so if the write to SQL Server failed or the the other service failed then it rolled back the data in SQL Server.  Definitely a real world example and it shows the ability of WCF to handle transactions.   

Wondering Around the Expo

After the Biztalk session I was walking from the north building back to the south building and ran into Bruce Thomas at the MVP booth.  I also saw Joe Healy, Jeff Palermo, DonXML, Miguel Castro, and Joe Fuentes.  I then walked down and caught some of the “Speaker Idol” that Carl Franklin and Richard Campbell were hosting.  This was pretty cool and I wish I had heard about it sooner so I could have entered.  The way it works is a speaker gets up on stage and does a 5 minute presentation.  Then they get judged by a bunch of Regional Directors.  It is a really great way to get feedback about your presentation skills no doubt.  The big challenge is doing just a 5 minute talk!

Smart Client Applications in Visual Studio 2008

After lunch I went to a presentation on the new smart client features in Visual Studio.  Some of these are nothing new in terms of new information (linq and wpf) but they are technically “new” in 2008 and some are new exciting features.

Working With Data

LINQ is of course the new way to work with data in VS2008.  The demos they showed were just connecting to a database locally which isn’t a true Smart Client architecture in my opinion since it isn’t services based.  Nevertheless, LINQ is new in VS2008 and we’ll all love him, hug him and call him George.

Taking Data Offline

This is something that I hadn’t seen yet and it really peaked my interest since we have a lot of uses for it.  SQL Server Compact Edition 3.5 which is in beta right now will be available to us.  You can read about the new features here.  The nice thing about 3.5 is it can be deployed with your application through ClickOnce and it doesn’t run as a service.  It also supports about 2-4 GBs of data which should be PLENTY for any application that needs to run offline.  The other piece is the Sync Agent which is tasked with the joy of keeping data in sync.  As soon as they said this I immediately thought “Smart Clients shouldn’t connect to the database directly” and as soon as I thought that the presenter said it supports sync via services.  Hotness! 

User Profiles

Something else that is new is Client Application Services.   Today web applications can store user profile information which is used for themes, preferences and so on but it is tough for Smart Clients that are service enabled.  Client Application Services allows us to reuse the existing profile and role based mechanisms Asp.Net offers today to allow us to centrally store profile information.  This may not sound like a big deal but today we have to create a lot of plumbing in Smart Clients to store application preferences and profile information away from the client’s desktop machine.  Storing preferences on the desktop machine doesn’t allow users to move from machine to machine and have the application setup the same way. Client Application Services fixes this by leveraging existing functionality so this will be good.  There will be a new services tab when you right click on properties on your project.  In the services tab you point to a web server which will hold the profile settings and any settings you create in your app are stored and retrieved from there. 

User Experience

Another new feature in VS2008 is going to be WPF.  They call this the “user experience” but a lot of us already know about WPF.  This will change how we build Smart Clients no doubt but we’ve been hearing about WPF since 2005 so nothing to see here.  Moving on.

Deployment

In VS2005 we got a new deployment technology called ClickOnce.  In VS2008 ClickOnce doesn’t go away, it just gets enhanced.  There are six new enhancements to it but the one I like the best is the ability to change the deployment URL and not have to rebuild the entire manifests.  I didn’t write them all down but there was something mentioned about ISV branding in ClickOnce in VS2008. 

Reusability – Acropolis

This was the new bomb shell that was dropped called “Acropolis”.  Acropolis is a framework that simplifies building composite clients and will replace the Smart Client Software Factory moving forward.  Bryan Adams just blogged about this on June 4th so read his initial post if this is your first time to hear about it (just remember you heard it hear first 🙂 ).  After you read that, read this one with more questions and this one with additional information including video and live docs.

Certification Study Hall

After the what’s new in Visual Studio 2008 I went to the certification center where I started practicing some certification exams.  At TechEd you can take certification exams for $50 here onsite as well as go through tons of test questions.   I studied until I just about fell asleep and then rolled to the hotel.  Day two is now in the books.