SyntaxHighlighter

Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Wednesday, May 16, 2012

Handle HTTP Form Post requests with a WCF service

I have been spending a lot of time working with WCF of late and one of my goals were to build an interface capable of handling HTTP Post requests. My inspiration comes from the fantastically simple implementation by Stripe:

curl https://api.stripe.com/v1/charges \  
   -u vtUQeOtUnYr7PGCLQ96Ul4zqpDUO4sOE: \  
   -d amount=400 \  
   -d currency=usd \  
   -d "description=Charge for site@stripe.com" \  
   -d "card[number]=4242424242424242" \  
   -d "card[exp_month]=12" \  
   -d "card[exp_year]=2012" \  
   -d "card[cvc]=123"

Let's see how we can create a similar implementation using WCF.

In Visual Studio 2010, create a new WCF Service Application, which we're going to call the Network. The following files will be created within your project:

  • IService1.cs Your service contract
  • Service1.svc The service implementation 
  • Web.config Your service configuration information
You can rename these, but I'll leave them as they are, since renaming them can cause complications later on.

Let's start with our service interface. By default VS will generate two service methods (GetData and GetDataUsingDataContract) and a class called CompositeType. You can remove the methods and class and replace it with the following:

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace Network
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "ping")]
        string Ping(Stream input);
    }
}

The key here is to add the WebInvoke attribute. The UriTemplate indicates which URL will be mapped to this particular method call. In our case, Ping(...) will be executed if any HTTP Post request is sent to http://localhost:port/service1.svc/ping.

Next we need to implement our service. Essentially we are just pinging our service with some message which will be echoed back.

using System;
using System.Collections.Specialized;
using System.IO;
using System.Web;

namespace Network
{
    public class Service : IService1
    {
        public string Ping(Stream input)
        {
            var streamReader = new StreamReader(input);
            string streamString = streamReader.ReadToEnd();
            streamReader.Close();

            NameValueCollection nvc = HttpUtility.ParseQueryString(streamString);
            return string.IsNullOrEmpty(nvc["message"]) 
                ? "The 'message' key value pair was not received."
                : nvc["message"];
        }
    }
}

All we need to do now is to configure our service in the web.config. The key here is to create a  webHttpBinding endpoint with a corresponding webHttp endpointBehavior:

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webEndpointBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="Network.Service1">
        <endpoint address="" 
                  behaviorConfiguration="webEndpointBehavior" 
                  binding="webHttpBinding" 
                  bindingConfiguration="" 
                  contract="Network.IService1"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Now we can run our service. For consistency, we'll use the VS Development Server as our host and specify a static port. Go into the project properties, select the Web tab and set the Specific Port to 8000.

Set your Service.svc as the start page, and build and debug.

You can either create a plain HTML page with a form that posts to your service or you can use a tool such as curl to do a submission. Let's put it to the test:

c:\>curl http://localhost:8000/service1.svc/ping -d message=pong
"pong"

Success!

Update:
If you'd like to test this solution from a web page, you can use the following bit of HTML code:
<html>
  <body>
    <form action="http://localhost:8000/service1.svc/ping" method="post">
      <input name="message" type="text" value="pong" />
      <input type="submit" />
    </form>
  </body>
</html>
The response received is:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">pong</string>
One might want to get rid of the tags around the response string as well, but I'll get back to that in another post.

Tuesday, February 8, 2011

WCF: Programmatically set dataContractSerializer's maxItemsInObjectGraph value

When programmtically setting up a WCF Client, one often have to set the dataContractSerializer's maxItemsInObjectGraph parameter (within the serviceBehaviors) to a higher value than the default 65536.

I struggled a bit to find this one on-line, but finally came across a solution on here.

Here's the way to do it:
foreach (OperationDescription operation in myClient.Contract.Operations)
   operation.Behaviors.Find<DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = 2147483646;


Where the myClient object is an instance of the ServiceClient.

Monday, March 29, 2010

WPF: Dynamically create a Table

Being new to WPF, there are a few funnies you'd need to know about before being able to create a simple table with text.

First, one can't simply add a Table within a Grid container. Tables need to be housed within a FlowDocument. One also need a container to display these FlowDocuments. I found the FlowDocumentScrollViewer to be the simplest. Some code to display a blank table:
<FlowDocumentScrollViewer
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled">
<FlowDocument>
<Table Name="myTable"></Table>
</FlowDocument>
</FlowDocumentScrollViewer>

To populate the table programmatically with some basic text one need to follow the next procedure (the code is pretty much self-explanatory):
int cols = 5;
int rows = 10;

for (int c = 0; c < cols; c++)
myTable.Columns.Add(New TableColumn());

for (int r = 0; r < rows; r++)
{
TableRow tr = new TableRow();

for (int c = 0; c < cols; c++)
tr.Cells.Add(New TableCell(New Paragraph(New Run("Some Text"))));

TableRowGroup trg = new TableRowGroup();
trg.Rows.Add(tr);
myTable.RowGroups.Add(trg);
}

I must say that this approach (a Run within a Paragraph within a TableCell within a Row within a RowGroup) isn't terribly intuitive and the process seems a bit tedious when only trying to create a simple table.

Thursday, December 10, 2009

C#: Calling/Overriding Grandparent Base Class Methods

I use a base class for 99% of my ASP.Net pages, which executes a few operations in the OnInit() method. Here's a simplified version:
public abstract class BasePage : System.Web.UI.Page, IBasePage
{
protected override void OnInit(EventArgs e)
{
// Do stuff
Method1();
Method2();
Method3();

// Call System.Web.UI.Page.OnInit
base.OnInit(e);
}
}
This works great for all my child classes/pages, but there are a few scenario's where I'd only like to call a specific set of methods, as illustrated here:
public class MyPage: BasePage
{
protected override void OnInit(EventArgs e)
{
// Ommit Method2()
Method1();
Method3();

// This calls BasePage.OnInit, which makes
// redudant calls to Method1() and Method3(),
// and the undesired call to Method2().

base.OnInit(e);
}
}
It is obvious that the last base.OnInit(e) call will have the undesired effect. Being 6:23 PM, after coding all day, my fried brain's initial thought was to bypass the base class' OnInit(e) method and to call the grandparent's OnInit(e) method directly.

An obvious faux pas. Whenever venturing into the "grandparent" or "grandchild" realm (more than one degree of seperation), you're probably going down the wrong path.

The proper and easy approach is merely to move the method calls out to a seperate method, which one overrides in the child class like so:
public abstract class BasePage : System.Web.UI.Page, IBasePage
{
protected override void OnInit(EventArgs e)
{
// Do stuff
Initialize();

// Call System.Web.UI.Page.OnInit
base.OnInit(e);
}

protected virtual void Initialize()
{
Method1();
Method2();
Method3();
}
}

public class MyPage: BasePage
{
protected override void Initialize()
{
// Do stuff
Method1();
Method3();
}
}

Monday, November 23, 2009

Type 'DataContract' is not defined

This error can be resolved by adding a reference to the .net System.Runtime.Serialization assemly and also importing this namespace in the file where applicable.

Also, applies to Type 'DataMember' is not defined.

Wednesday, August 13, 2008

Constraint cannot be special class 'object'

I was busy creating a generic method to convert a List to a DataTable when I received the error:
Constraint cannot be special class 'object'
on this statement:
public DataTable ListToDataTable(IList list) where T : Object

Blegh... why would this be? Anyhow, I did a workaround by changing the statement to the following:
public DataTable ListToDataTable(T list) where T : IList

A bit annoying, since now one has to send a List and can't simply pass a List.

Another workaround is to use a blank interface, with the statement as:
public DataTable ListToDataTable(IList list) where T : IBlank

Now one can send List if MyClass 'implements' the IBlank interface.

I'm not really too happy with any of these workarounds. I see no reason why the Object class is "too special" to be used as a generic placeholder.

Oh, and merely for interest sake. Here is the generic List to DataTable converter method:
public DataTable ListToDataTable(List list) where T : IBlank
{
DataTable dataTable = new DataTable();

Type type = typeof(T);
PropertyInfo[] properties = type.GetProperties();

// Create the columns
foreach (PropertyInfo property in properties)
dataTable.Columns.Add(property.Name, property.PropertyType);

// Populate the rows
foreach (T obj in list)
{
DataRow newRow = dataTable.NewRow();

foreach (PropertyInfo property in properties)
newRow[property.Name] = property.GetValue(obj, null);

dataTable.Rows.Add(newRow);
}

return dataTable;
}

Friday, July 11, 2008

Named pipes issue: System.UnauthorizedAccessException: Access to the path is denied.

After yesterday's triumphant discovery I had a nightmare of a day trying to figure out why my client couldn't connect to the server. Time and time again, the following exception was raised:

System.UnauthorizedAccessException: Access to the path is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.Pipes.NamedPipeClientStream.Connect(Int32 timeout)
at System.IO.Pipes.NamedPipeClientStream.Connect()
And in the debug output window:
A first chance exception of type 'System.UnauthorizedAccessException' occurred in System.Core.dll

My best googling skills couldn't find an answer for this one and I ended up trying to change the permission for the NamedPipeServerStream and venturing down the wrong path by changing the PipeAuditRule and PipeAccessRule settings.

In the end turned out my PipeDirection had to be set to InOut, even though I was only streaming information from the Server, and not receiving information.

Here's the winning line of code:

NamedPipeServerStream Pipe = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1,
PipeTransmissionMode.Message, PipeOptions.None);

Tuesday, July 8, 2008

Windows Service uninstall failed

Whilst developing a Windows Service, an exception occurred. I opted not to debug and when I exited the VS instance the service naturally terminated.

When I got back into the Services MMC, my service was marked as Disabled. When trying to uninstall the service through InstallUtil myservice.exe /u, the following exception was raised:

An exception occurred during the Install phase.
System.ComponentModel.Win32Exception: The specified service has been marked for deletion


This problem is easy enough to solve. Just quit the MMC and uninstall the service again.

Thursday, July 3, 2008

UI updates and threading

I've been working on a small Windows Forms app which has a thread running in the background. This read needs to send info back to the UI during certain intervals. It's a pretty easy problem to solve and there are numerous sources on the web explaining this.

I did come across weird behaviour when my app went into a deadlock. It hanged at the Invoke method in the following code:
// This updates some control safely
protected void UpdateSomeControl()
{
// Check if an Invoke is required
if (InvokeRequired)
{
// Update the UI through delegation
Invoke((ThreadStart)delegate()
{
// ... Update the UI ...
});
}
else
{
// ... Update the UI ...
}
}
This is upposed to work! So what happened?

Turns out there are two types of calls to modify a control in .Net. The first is a SendMessage and the other PostMessage. Invoke uses SendMessage, which causes the update message to be sent, but hangs around until the message has been processed. BeginInvoke uses PostMessage which is basically a fire-and-and-forget approach; the message is added to the queue and the process goes of doing other work without waiting for it to processed.

So my Invoke was obviously hanging around waiting for the control update to be completed, while the control update was waiting for some other process further back in the queue... at least that's how I understand it.

To solve this issue, simply use BeginInvoke rather than Invoke. I'm sure this fix is not appropriate for all problems, but in my case it did the trick.

For a more detailed explenation, see this CodeProject page.