Tuesday, August 9, 2016

Using HTML in a Web.config file

I wanted some pop up contextual help in an app I was writing. I got to the point where my requirements were:

  1. Use the bootstrap "popover" so I could include HTML and style the pop-up
  2. Include the help text in the config so it could be easily changed in the future 
Here's how I did it. 

Step 1: add a new section to web.config – this will prevent the text from needing to be escaped or treated with any special handlers

<section name="contextHelp" type="System.Configuration.IgnoreSectionHandler" allowLocation="false" />

Step 2: add the values for the section – I’m using CDATA to hide the markup and that should be sufficient for hyperlinks or images too

    <groupTitle><![CDATA[A group title with specific identifying information will be easy to search for later.<br /><br />Use specific hierarchy to help.


Step 3: add code to read the config in the code-behind

protected string HelpTextTitle { get; set; }

protected new void Page_Init(object sender, EventArgs e)
  // Help Sections
  XmlDocument doc = new XmlDocument();
  HelpTextTitle = doc.SelectSingleNode("/configuration/contextHelp/groupTitle").FirstChild.Value;

Step 4: add values into markup

<a href="#" rel="group_title"><i class="fa fa-question-circle"></i></a>
$(document).ready(function () {
             title : 'Group Title', 
             html: 'true', 
             trigger: 'focus', 
             content: '<%=HelpTextTitle %>'

Friday, July 15, 2016

Authenticating with Web Services written in a different language

Ah, the great promise of web services! We'll all speak the same language, XML/SOAP/JSON! Yeah, not so much. My latest interaction with this was a service that wanted a WS-Security authentication header but didn't want all the fields that Microsoft uses by default; without laying blame my understanding is some Java-based services don't accept a timestamp and this was my experience. Here's how I solved the problem:

WCF wasn’t really an option; because one of the functions had a callback it wanted to do duplex communication which among other things doesn’t support SSL. So here’s what I did:
  1.  Added WSE3 to the project (Microsoft.Web.Services3.dll)

  2. Create an old-school Web Reference in .NET (advanced option in “Add Service Reference”)

  3. Changed the resulting Referencs.cs class from System.Web.Services.Protocols.SoapHttpClientProtocol to Microsoft.Web.Services3.WebServicesClientProtocol

  4. Created a policy to allow me to filter the SOAP

  5. public class ClientUserNamePolicyAssertion : SecurityPolicyAssertion
            public string UserName { get; set; }
            public string Password { get; set; }
            public ClientUserNamePolicyAssertion(string userName, string password)
                this.UserName = userName;
                this.Password = password;

            // and let the assertion know you have an output filter for outgoing SOAP packets
            public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
                return new ClientSendSecurityFilter(this);

            public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
                throw new NotImplementedException();

            public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
                throw new NotImplementedException();

            public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
                return null;

  6. Created the filter – here is where I remove the timestamp header, right before the packet goes out

  7. public class ClientSendSecurityFilter : SendSecurityFilter
            private ClientUserNamePolicyAssertion clientUserNamePolicyAssertion = null;

            public ClientSendSecurityFilter(ClientUserNamePolicyAssertion userNamePolicyAssertion)
                : base(userNamePolicyAssertion.ServiceActor, true)
                this.clientUserNamePolicyAssertion = userNamePolicyAssertion;

            public override void SecureMessage(SoapEnvelope soapEnvelope, Security security)
                UsernameToken usernameToken = new UsernameToken(clientUserNamePolicyAssertion.UserName, clientUserNamePolicyAssertion.Password, PasswordOption.SendPlainText);

            public override SoapFilterResult ProcessMessage(SoapEnvelope envelope)
                // go ahead and run the base so the headers and security are added
                SoapFilterResult res = base.ProcessMessage(envelope);

                // remove the timestamp from the security header
                foreach (XmlNode n in envelope.Header.ChildNodes) {
                    if (n.Name == "wsse:Security")
                        foreach (XmlNode p in n)
                            if (p.Name == "wsu:Timestamp") n.RemoveChild(p);


                return res;

  8. Then in the main I can create the service, apply my policy and make calls

TheirJavaService svc = new TheirJavaService();
ClientUserNamePolicyAssertion assert = new ClientUserNamePolicyAssertion("myusername", "mypassword");
Policy policy = new Policy();
TheirServiceRequest req = new TheirServiceRequest();
TheirServiceResponse res = svc.GetResponseFromTheirService(req);