skip to Main Content

Considerations When Throwing Exceptions

A co-worker sent an email with some code he’s struggling with. He’s trying to avoid using try/catches to drive business logic.

The problem is not the try/catches it’s simply a symptom of the problem. Can you spot the problem? You’ll have to make some assumption, but I have faith you’ll come to the same conclusion I came too.

The code is below; I changed it to protect the innocent:

private Customer GetOrCreateCustomer(long customerTelephoneNumberOrCustomerId)
        {
           Customer customer;
            try
            {
                customer = this.DoMagic(customerMasterTelephoneNumberOrCustomerId);
            }
            catch (DataException)
            {
                try
                {
                    //TODO: I know this isn't ideal. Still thinking of a better way to do this. 
                    customer = this. GetCustomer(customerMasterTelephoneNumberOrCustomerId);
                }
                catch (DataException)
                {
                    customer = this.GetCustomerFromExternal(customerMasterTelephoneNumberOrCustomerId);
                    customer.CustomerId = this.CreateCustomer(customer);
                }
            }

            return customer;
        }

There is an underlining philosophy in this system that nulls are bad. In most cases where a null can be generated an exception is thrown. At first I did not see a problem with this. I saw it as an architecture decision, an aesthetic, but as I interface with the code, it’s apparent to me it’s an architectural mistake.

You might ask, why is throwing an exception in the case of nulls bad?

Below are some guidelines when considering throwing an exception:

  1. The fact that you have to check for the null to throw the exception should be a hint that it is not needed. It an expected outcome, thus not an exception.

  2. Throwing an exception is a resource intensive operation, one of the most resource intensive operations that can be done in .Net.

  3. An exception is just that, an exception. It’s an exception to the assumptions made in the code – when these assumptions are broken, the system must terminate, it cannot move on because the system is in an unknown state (i.e. the database is no longer available) this could also be an attack vector.

  4. Throwing an exception means you have to wrap the upstream call in a try/catch block to enforce business rules. A null value is a business opportunity to control the flow of the application. The action upon the null value should be done at the point in which a business decision must take place. For example, a customer variable is null, at the UI layer a message is shown to the user stating the customer with id ‘1234’ cannot be found.

Setting up Single Sign On with Windows 2012 and ASP.Net MVC 4

Requirements

  • Windows 2012
  • AD FS 2.0 Feature installed
  • ASP.Net MVC 4.0
  • Valid SSL certs
  • Visual Studio 2012
    This document covers setting up an ASP.NET MVC 4.0 application using Visual Studio 2012, Windows 2012 and AD FS 2.0 to enable Web Single Sign On.

It’s important to have valid SSL certificates. Self signed certificates will not work. SSL certificates are used to encrypt the tokens and will not work with self-signed certificates. This is very important. If you do not have valid certificates this will not work. Don’t waste your time without valid certificates.

Setting up AD FS 2.0 on Windows 2012

Assuming Windows 2012 is installed. With a valid SSL certificate install the SSL certificate in IIS. This is done by opening IIS (7+) Management Console, selecting the root web server node and opening the Server Certificates found in the Feature view. Do not install the AD FS feature before installing the certificate. AD FS extracts the host name from the SSL certificate and will use localhost if a certificate is not found.

If AD FS is installed before installing the SSL certificates

If this does happen, you’ll need to uninstall the the AD FS role and manually delete the IIS applications (removing them from the IIS management console is not enough they must be removed from the IIS metabase via the command line).

C:WindowsSystem32inetsrvappcmd.exe delete app "Default Web Site/adfs"
C:WindowsSystem32inetsrvappcmd.exe delete app "Default Web Site/adfs/ls"

Once a valid certificate is installed the AD FS role can be installed.

When reinstalling ADFS, the relying party needs to rebind to AD FS’s FederationMetadata otherwise you’ll encounter an ASP.Net error stating there was a token error.

Federation Services URL

At times this url uses localhost as the host. I am not certain of the cause, but unless localhost is the domain used in the ssl cert, it will not work. The following link describes how to change it.
http://technet.microsoft.com/en-us/library/dd353709%28v=ws.10%29.aspx

At this point AD FS is setup on the server. However, it does not have any trusts established, with the exception of Active Directory (configured by default). The next step is to create a trust with a Relying party.

A trust is a relationship setup between the relying party(ASP.Net MVC) and the issuer (AD FS). The trust is setup on both the relying party and the issuer.

https://myhostname.com/federationmetadata/2007-06/federationmetadata.xml

Creating a Relying Party

Assuming you have installed Visual Studio 2012, download the Windows Identity Foundation Identity and Access Tool Extension tools. Once installed create a MVC 4 project. The option “Identity and Access” is added to the project right-click menu. The Windows Identity Foundation SDK might also be a requirement.

This brings up the Identity and Access option screen.

Enter the path to the STS metadata document

The STS metadata document is generated by the AD FS server. The FederationMetadata.xml defines the Issuer (sometimes referred to as the Identity Server) and allows MVC 4(Relying Party) to create a trust between itself and the Issuer.

Enter the Realm for your Application

The realm is the MVC application. Unless the MVC application and the AD FS are on the same server the localhost host will not work. The realm is the url to your site.

Setting up a Relying Party Trust in AD FS

The Relying Party is created, now it’s time to set up the Relying Party Trust in AD FS. Back on the server open up AD FS MMC screen and click on “Add Relying Party Trust…”

The next screen asks for the FederationMetadata.xml from the relying party. In the previous step when the FederationMetadata.xml was added into the MVC 4 application a FederationMetadata.xml was created for the MVC 4 application. Now we must import the Relying Party FederationMetadata.xml into the AD FS server to complete the trust.

The FederationMetadata.xml can either be imported via a url or added via a local file. The default FederationMetadata.xml path is https://myhostname.com/FederationMetadata/2007-06/FederationMetadata.xml (same as it was for the AD FS server). If it successfully retrieves the FederationMetadata.xml you can click next until the end.

The next step is to add an endpoint. The endpoint is where a user is redirected to upon successful authentication. Start by clicking the Relying Party Trusts folder, you’ll see the Relying Party Trust that was just created. Right-click on it and select “Properties” a tabbed interface will appear. From the monitoring tab Uncheck “Automatically update relying party” this feature does not work out of the box.

Note: If the relying party is configured correctly this step is not necessary.

Click on the endpoint tab and click add. The “Add an Endpoint” dialog will appear. Select WS-Federation for the Endpoint Type. This will automatically set the Binding dropdown to “POST”. In the URL field enter the url in which an authenticated user is sent.

That’s it! The AD FS single sign on should prompt you for credentials. Once entered it will redirect you back to your site’s landing page.

Accessing AD FS with a non-IE browser

Out of the box you’ll encounter a dialog asking for username and password. For whatever reason it would not accept my domain credentials.

In a nutshell a property ExtendedProtectionTokenCheck is set to required when running windows 7. Only IE supports this feature.

More information on the issue
http://stackoverflow.com/questions/6309210/ntlm-authentication-to-ad-fs-for-non-ie-browser-without-extended-protection-sw

How to disable it
http://social.technet.microsoft.com/wiki/contents/articles/1426.ad-fs-2-0-continuously-prompted-for-credentials-while-using-fiddler-web-debugger.aspx

Troubleshooting Tips

1. Recompile the website and trying adding the trust for both ADFS and the web site.

2. Re-install AD FS, that had some issues also, but sometimes it getting to get a fresh start.

3. Installing ADFS Multiple times and you encounter a 503 on the FederationServerServices.asmx

Try removing the ACLs

netsh http delete urlacl url=http://+:80/adfs/services/
netsh http delete urlacl url=https://+:443/adfs/services/
netsh http delete urlacl url=https://+:443/FederationMetadata/2007-06/
netsh http delete urlacl url=https://+:443/adfs/fs/federationserverservice.asmx/

Continuing with the tips

4. When reinstalling ADFS after IIS was removed, the previous ADFS web directory under C:inetpubadfs* needs to be deleted.

5. The configuration service URL 'net.tcp://localhost:1500/policy' may be incorrect or the AD FS 2.0 Windows Service is not running.

setspn -l myservername

before

The SPN is not set or is incorrect. The following thread discusses it in more detail.

http://social.technet.microsoft.com/Forums/en-US/winserverDS/thread/cd9bc625-49f3-499b-9bf3-4ef32fbf64ec/

hint: casing does matter.

After

6. The X.509 certificate CN=ADFS Signing - mydomain.com is not in the trusted people store. The X.509 certificate CN=ADFS Signing - mydomain.com chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

This is not recommended for going into production, but it will get you past the issue:

http://social.technet.microsoft.com/wiki/contents/articles/windows-identity-foundation-wif-how-to-change-certificate-chain-validation-settings-for-web-applications.aspx

In Conclusion

My overall experience with AD FS 2.0 and Windows 2012 has been painful. Working with AD FS 2.0 reminds me of working with Sharepoint 2010 in the early days.

Some of the configuration is done differently on the Windows 2012 server versus in Visual Studio, even though you are doing the same exact things (i.e. setting up a trust). Once the server is setup and the trusts are established and working correct it’s a thing of beauty, until you get there, good luck!

Creating a Generic Type at Runtime

I have a type (at runtime), I want to use it with an IOC container (in this case StructureMap) to find a generic implementation using this type. How do I do that?

It’s simpler than you’d think:

Type genericType = typeof (AbstractValidator);
Type type = genericType.MakeGenericType(bindingContext.ModelType);

//Structure Map container
var instance = _container.GetInstance(type);

Deploying with MsDeploy Outside of Visual Studio

Building the msdeploy package with MSBuild.

This requires MsDeploy to be installed on the build machine.

MSBUILD /T:Package /P:Configuration=QA;PackageLocation="C:\Build\Artifacts\eserve\DEV\QA\QA.zip"

Deploying the package with MsDeploy to a web site

How to get the msdeploy command.

-source:package='C:BuildArtifactseserveDEVQAQA.zip' -dest:auto,ComputerName='https://eserve-dev.sacda.org:8172/MsDeploy.axd?site=eserve-dev',UserName='conwayc',Password='austin_1',IncludeAcls='False',AuthType='Basic' 
-verb:sync 
-disableLink:AppPoolExtension 
-disableLink:ContentExtension 
-disableLink:CertificateExtension 
-allowUntrusted 
-retryAttempts=2

Copying the package with ROBOCOPY

Copying the package to another folder with robocopy has an issue. Robocopy uses exit codes as success/error codes. CI servers look at the exit code of a command to determine success or failure. Robocopy breaks this model. Luckliy the sql team posted a code snippet to get around this issue.

rem http://weblogs.sqlteam.com/robv/archive/2010/02/17/61106.aspx
robocopy %*
rem suppress successful robocopy exit statuses, only report genuine errors (bitmask 16 and 8 settings)
set/A errlev="%ERRORLEVEL% & 24"
rem exit batch file with errorlevel so SQL job can succeed or fail appropriately
exit/B %errlev%

Deploying from folder to site

-verb:sync -source:contentPath=C:BuildArtifactsSSOClientDEV -dest:contentPath="C:inetpubadfsls",computerName='http://customer.dev.myconsolidated.net
/MsDeployAgentService',userName=ccadmin,password=$urewest123

Change App Path at Commandline via MSBuild

/T:Package 
/P:Configuration=DEV;PackageLocation="C:\BuildArtifacts\Grover\Dev\Builds\DEV\Grover.zip";DeployIISAppPath=dev.grover.winnemen.com

Using MsBuild to deploy contents to folder

/T:PipelinePreDeployCopyAllFilesToOneFolder /P:Configuration=QA;_PackageTempDir="C:Build\Artifacts\Momntz\DEV\Builds\QA

Deploying Local with MSDeploy

"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:package='C:\BuildArtifacts\AlSupport.zip' -dest:auto,computerName='localhost' -allowUntrusted -retryAttempts=2 -verbose

Deploying folder to Azure with MSDeploy

The following command line is for deploying a folder to windows azure websites.

"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:contentPath="C:\TeamCity\buildAgent\work\d018513aed1c09f\Build" -dest:contentPath="groverqa",wmsvc=waws-prod-bay-005.publish.azurewebsites.windows.net/msdeploy.axd?site=groverqa,userName=$groverqa,password=secret,authtype='Basic' -AllowUntrusted

Code Refactor

On a recent project, I was tasked with refactoring large parts of a web system. It’s written in C#. Over time some of the code-behind files had grown to 4000 lines. The goal was to get this number down to a more maintainable level.

Over the next few posts, I’ve taken snippets of code that I refactored and will explain my thoughts and how I arrived at the solution.

The first code snippet:

    string tmp = Request.QueryString["st"];
    _varStartRecNum = tmp;
    if ((tmp != null) & (!Page.IsPostBack))
    {
        _varStartRecNum = tmp;
        postBack = true;
    }

    tmp = Request.QueryString["det"];
    if ((tmp != null) & (!Page.IsPostBack))
    {
        _varDetailsRecNum = tmp;
        postBack = true;
    }

    tmp = Request.QueryString["return"];
    if ((tmp != null) & (!Page.IsPostBack))
    {
        postBack = true;
    }

    tmp = Request.QueryString["searchnow"];
    if ((tmp != null) & (!Page.IsPostBack))
    {
        Session["selectedTab"] = "mtf";
        Session["sessionDSProviders"] = null;
        Session["mtfs"] = null;
    }

    tmp = Request.QueryString["displaywalking"];
    if (tmp == "true")
    {
        dispMtf = false;
        postBack = true;
    }

    tmp = Request.QueryString["sb"];

    if ((tmp != null) & (!Page.IsPostBack))
    {
        _varSortBy = tmp;
        postBack = true;
        switch (_varSortBy)
        {
            case "Distance":
            case "Drive time":
                ddlSortBy.SelectedIndex = 0;
                break;
            case "Name":
                ddlSortBy.SelectedIndex = 1;
                break;
            case "Gender":
                ddlSortBy.SelectedIndex = 2;
                break;
            case "Clinic":
                ddlSortBy.SelectedIndex = 3;
                break;
            case "City":
                ddlSortBy.SelectedIndex = 4;
                break;
            case "Description":
                ddlSortBy.SelectedIndex = 5;
                break;
        }
    }

The above code snippet is a collection of if statements, which are an evaluation and an execution. In my first attempt, I tried to use the same evaluation for all if statements, but then I realize one was different. Not understanding the intent of the code I am forced to preserve the logic in verbatim.

Different if evaluation:

tmp = Request.QueryString["displaywalking"];
if (tmp == "true")
{
    dispMtf = false;
    postBack = true;
}

The switch statement concerned me. The condition to enter into the switch statement is the same as the others. I decided to proceed and worry about the switch statement later.

The code uses the same variable, the ‘tmp’ variable, to retrieve different query value. The value is overwritten with each query value retrieval. For clarity I create a variable for each query value:

string st = Request.QueryString["st"];
string det = Request.QueryString["det"];
string @return = Request.QueryString["return"];
string searchNow = Request.QueryString["searchnow"];
string displayWaling = Request.QueryString["displaywalking"];
string sb = Request.QueryString["sb"];

The next step was to isolate the evaluation and expression while keeping them associated with each other. If an evaluation is true, I want to execute its corresponding expression. I created a class that represented the association.

private class Evaluate
{

    public Func Evaluation { get; set; }

    public Action Expression { get; set; }
}

Now I can create an evaluation, and if it’s true, I can execute its expression.

The next problem was how to use the above class with all the if statements. I was worried the expressions might get unwieldy in a collection. The whole purpose was to create a concise scaleable solution. The existing solution was neither.

var eval = new[]
               {
                   new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(st) && !IsPostBack), Expression = () => { _varStartRecNum = st;postBack = true; }},
                   new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(det) && !IsPostBack), Expression = () => { _varStartRecNum = det;postBack = true; }}, 
                   new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(@return) && !IsPostBack), Expression = () => {postBack = true; }}, 
                   new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(searchNow) && !IsPostBack), Expression = () => {Session["selectedTab"] = "mtf";Session["sessionDSProviders"] = null; Session["mtfs"] = null;}}, 
                   new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(displayWaling)), Expression = () => {dispMtf = false; postBack = true;}}, 
                   new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(sb) && !IsPostBack), Expression = () => {_varSortBy = sb;postBack = true; SetSort(_varSortBy);}}, 
               };

It turned out better than I expected. One drawback with my solution is, if you don’t know how to use delegates, you’ll be screwed when it comes to maintaining the above code.

The last stumbling block was the switch statement. It was not going to fit gracefully into my anonymous collection, but then it didn’t need to:

private void SetSort(string sortBy)
{
    switch (sortBy)
    {
        case "Distance":
        case "Drive time":
            ddlSortBy.SelectedIndex = 0;
            break;
        case "Name":
            ddlSortBy.SelectedIndex = 1;
            break;
        case "Gender":
            ddlSortBy.SelectedIndex = 2;
            break;
        case "Clinic":
            ddlSortBy.SelectedIndex = 3;
            break;
        case "City":
            ddlSortBy.SelectedIndex = 4;
            break;
        case "Description":
            ddlSortBy.SelectedIndex = 5;
            break;
    }
}

By encapsulating it into a method, I was able reference the method in the expression. It worked every nicely.

new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(sb) && !IsPostBack), Expression = () => {_varSortBy = sb;postBack = true; SetSort(_varSortBy);}

The last component is iterating over the collection:

foreach (var evaluate in eval.Where(evaluate => evaluate.Evaluation()))
{
    evaluate.Expression();
}

The complete solution:

private class Evaluate
{
    public Func Evaluation { get; set; }

    public Action Expression { get; set; }
}

private void SetSort(string sortBy)
{
    switch (sortBy)
    {
        case "Distance":
        case "Drive time":
            ddlSortBy.SelectedIndex = 0;
            break;
        case "Name":
            ddlSortBy.SelectedIndex = 1;
            break;
        case "Gender":
            ddlSortBy.SelectedIndex = 2;
            break;
        case "Clinic":
            ddlSortBy.SelectedIndex = 3;
            break;
        case "City":
            ddlSortBy.SelectedIndex = 4;
            break;
        case "Description":
            ddlSortBy.SelectedIndex = 5;
            break;
    }
}

private void EvaluateQueryParameters()
{
    string st = Request.QueryString["st"];
    string det = Request.QueryString["det"];
    string @return = Request.QueryString["return"];
    string searchNow = Request.QueryString["searchnow"];
    string displayWaling = Request.QueryString["displaywalking"];
    string sb = Request.QueryString["sb"];

    var eval = new[]
                   {
                       new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(st) && !IsPostBack), Expression = () => { _varStartRecNum = st;postBack = true; }},
                       new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(det) && !IsPostBack), Expression = () => { _varStartRecNum = det;postBack = true; }}, 
                       new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(@return) && !IsPostBack), Expression = () => {postBack = true; }}, 
                       new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(searchNow) && !IsPostBack), Expression = () => {Session["selectedTab"] = "mtf";Session["sessionDSProviders"] = null; Session["mtfs"] = null;}}, 
                       new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(displayWaling)), Expression = () => {dispMtf = false; postBack = true;}}, 
                       new Evaluate {Evaluation = () => (!string.IsNullOrEmpty(sb) && !IsPostBack), Expression = () => {_varSortBy = sb;postBack = true; SetSort(_varSortBy);}}, 
                   };

    foreach (var evaluate in eval.Where(evaluate => evaluate.Evaluation()))
    {
        evaluate.Expression();
    }
}

In the end, I like this solution better than the original. One of the drawbacks is the level it’s written. I wanted to create a simpler solution that any developer could maintain. There isn’t anything difficult about the above code; I’m creating a collection and iterating over it. The confusion comes in with the evaluation and the expressions. It’s not a beginner topic.

Back To Top