Accessing Web.Config...

Topics: Web Api
May 17, 2011 at 12:21 AM

I've made a custom channel to authenticate a custom header that is passed with requests. The code is based on this: http://wcf.codeplex.com/discussions/257491. Code works perfectly.

The custom header is a Shopify store ID (a making a web hook for my store). At the moment, I'm storing the ID in the web.config file in the app settings (encrypted). The problem is, when I try to access these settings in the authenication channel, I get an Object reference error.

Is it possible to even access the web.config file here?

May 17, 2011 at 2:48 AM

I have my custom channel in another assembly that does not have a reference to System.Configuration.  So, in order to gain access to ConfigurationManager, this can be done with or without the use of an IoC container.  If not using a container, in global.asax.cs you would do:

	var appSettings = ConfigurationManager.AppSettings;

	IHttpHostConfigurationBuilderAdvanced configurationBuilder = HttpHostConfiguration.BuildAdvanced()
		.SetMessageHandlerFactory(new CustomHttpMessageChannelFactory(appSettings))

then in your custom factory:

	private readonly NameValueCollection appSettings;

	public CustomHttpMessageChannelFactory(NameValueCollection appSettings)
	{
		this.appSettings = appSettings;
	}

	protected override HttpMessageChannel OnCreate(HttpMessageChannel innerChannel)
	{
		return base.OnCreate(new CustomChannel(innerChannel, appSettings));
	}

then in your custom channel:

	public CustomChannel(HttpMessageChannel innerChannel, NameValueCollection appSettings)
		: this(innerChannel)
	{
		this.appSettings = appSettings;
	}

If you're using IoC, it should be clear how to proceed from here.

Jun 5, 2011 at 9:03 AM

Thanks for the reply David.

I don't suppose you could explain in a little more detail on what to do? I haven't a clue on how to create a custom factory - the samples don't have any to base them off - or at least that I could find.

Jun 6, 2011 at 11:08 PM
RogerWilco wrote:

Thanks for the reply David.

I don't suppose you could explain in a little more detail on what to do? I haven't a clue on how to create a custom factory - the samples don't have any to base them off - or at least that I could find.


The only thing missing from the code snippets above was the actual "class wrapper" around the block in the middle.  I.e.:

	public class CustomHttpMessageChannelFactory
	{
		...
	}

 If you didn't create a custom factory, what syntax are you using to plug your custom channel?

Jun 6, 2011 at 11:16 PM

Here is my custom channel:

Imports System.Net.Http
Imports System.Threading
Imports System.Threading.Tasks

''' <summary>
''' Custom channel for WCF Web API to verify if the incoming request contains the Shopify store ID.
''' </summary>
Public Class StoreVerificationChannel

    Inherits DelegatingChannel

    Public Sub New(ByVal handler As HttpMessageChannel)
        MyBase.New(handler)
    End Sub

    Protected Overrides Function SendAsync(ByVal request As HttpRequestMessage, ByVal cancellationToken As CancellationToken) As Task(Of HttpResponseMessage)

        ' Does the incoming request contain the Shopify store header?
        If request.Headers.Contains("X-Shopify-Shop-Id") = True Then

            ' Get the HTTP headers from the incoming request and search for the store ID.
            Dim headers As IEnumerable(Of String) = request.Headers.GetValues("X-Shopify-Shop-Id")
            If headers.First <> "xxxxx" Then ' todo: move to config.
                Return Task.Factory.StartNew(Function() New HttpResponseMessage(System.Net.HttpStatusCode.Forbidden, "Go away!"))
            End If

        Else
            Return Task.Factory.StartNew(Function() New HttpResponseMessage(System.Net.HttpStatusCode.Forbidden, "Go away!"))
        End If
        Return MyBase.SendAsync(request, cancellationToken)

    End Function

End Class

And on appication start:

 config.AddMessageHandlers(GetType(StoreVerificationChannel))