Comparing String Concatenation in C#

I have always heard you should avoid string.format because it has to create a System.Text.StringBuilder object. With the introduction of
string interpolation in C# I wanted to see how some of the different concatenation options performed.

Here is the test code I ran in linqPad

var limit = 1000000;

var stopwatch = new Stopwatch();
stopwatch.Start();
for(var i = 0; i < limit; i++){
    var newString = $"This is a new{i} string with two {i} things inserted";
}
stopwatch.Stop();
"interpolation".Dump();
stopwatch.ElapsedMilliseconds.Dump();


stopwatch = new Stopwatch();
stopwatch.Start();
for(var i = 0; i < limit; i++){
    var newString = string.Format("This is a new {0} string with two {1} things inserted", i, i);
}
stopwatch.Stop();
"string.format".Dump();
stopwatch.ElapsedMilliseconds.Dump();


stopwatch = new Stopwatch();
stopwatch.Start();
for(var i = 0; i < limit; i++){
    var newString = "This is a new " + i + " string with two " + i + " things inserted";
}
stopwatch.Stop();
"concat".Dump();
stopwatch.ElapsedMilliseconds.Dump();


stopwatch = new Stopwatch();
stopwatch.Start();
for(var i = 0; i < limit; i++){
    var newString = string.Join("This is a new ", i, " string with two ", i, " things inserted");
}
stopwatch.Stop();
"string.Join".Dump();
stopwatch.ElapsedMilliseconds.Dump();

Here are the results. All the speed numbers are in milliseconds.

Iterations Interpolation string.Format concat string.Join
100 0 0 0 0
1,000 0 0 1 0
10,000 4 5 3 4
1,000,000 401 405 310 368

For all the fuss, I really expected the string builder to be much slower. My takeaway is you have to be above a million iterations before you can even see measureable differences. Therefore, unless you have an actual production performance problem, write whatever is easiest to read. The millisecond you save won’t matter if it costs you even 30 extra seconds to understand what the code is doing.

Using Marvin.JsonPatch and Swashbuckle to Generate Swagger Documents

We have been working to implement new API documentation.  Since ASP.net help pages are not going to be available in .net core we decided to move to Swagger.  In case you aren’t familiar with the pipeline, here are the basics. 

ASP.net help pages were generated from the .net source code.  Swagger documentation is generated from a JSON document.  Swashbuckle is the glue that generates the Swagger JSON from the .net code.  It’s beyond the scope of this document to talk about how awesome this stack is, but you should check it out. 

JSON Patch Documents

We are using the JSON patch documents to allow partial updates to our system.  Since parsing of these documents is not built into ASP.net by default, we are using the Marvin.JsonPatch nuget package.  This is working great for us, but the format of the JsonPatch<T> object that is the parameter to the controller method does not match the format of the JSON payload you have to send to the PATCH request. For example.

public HttpResponseMessage PatchLead([FromUri] int leadId, [FromBody] JsonPatchDocument<PatchLeadViewModel> patch)

The patch parameter has an Operations collection that you can process.  Since this collection is on the object, Swashbuckle generates the sample payload to look like this. 

{
   "Operations": [
     {
       "value": {},
       "path": "string",
       "op": "string",
       "from": "string"
     }
   ]
}

Unfortunately the correct JSON Patch payload looks like this.

[
   { "op": "replace", "path": "/baz", "value": "boo" },
   { "op": "add", "path": "/hello", "value": ["world"] },
   { "op": "remove", "path": "/foo"}
]

The Solution

Swashbuckle gives us some places we can tie into the JSON generation pipeline so we can customize the output.  One of those places is in the SchemaFilter.  SchemaFilters implement the ISchemaFilter interface which has a single method with this signature.

public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)

This fires for each of the controller method parameters during the Swagger JSON generation.  You can inspect the type, and if needed override the default output from Swashbuckle.  This is a class that looks for all parameters that implement JsonPatchDocument<T> and replaces the generated output with a simple JSON Patch document example. 

public class JsonPatchDocumentSchemaFilter : ISchemaFilter
{
     public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
     {
         if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(JsonPatchDocument<>))
         {
             schema.example = new[] {new Marvin.JsonPatch.Operations.Operation() {op = "replace", path = "/SamplePath", value = "UpdatedValue"}};
         }
     }
}

The last thing you have to do is register the SchemaFilter with Swashbuckle.  In the startup.cs file where you enable and configure Swashbuckle, you need to add the following.

config.EnableSwagger(c =>
     {
         ...
         c.SchemaFilter<JsonPatchDocumentSchemaFilter>();
     })
     .EnableSwaggerUi(c =>
     {
         ...
     });

Notes

While writing this we were using Marvin.JsonPatch v 0.9.0 and Swashbuckle.Core v5.5.3

IIS Express-The Specified Port Is In Use

So you’re in the zone, been coding all day, have all tools in just the right spot.  Then BAM!  The dreaded port is in use.

Port is in use error image

Reading about this issue on stack overflow some people say its been chrome that has the port, or sometimes another process.  For me, It’s always some orphaned or hung IIS Express process holding onto the port.  Rarely, trying to start the debugger again will let you continue, but most of the time I had to resort to a reboot.  This is obviously inconvenient and a waste of time.  So here’s another option. 

Get PS Kill

The PS Tools are awesome you should check them out.  All we need today is PSKill.  Install/Extract is as you see fit and make sure you can access it from the command line. 

Netstat knows who is using the port

Run this from the command line.

netstat –ano | findstr <port> (in this case netstat –ano | findstr 62646)

The n is really important.  It prevents trying to resolve all the DNS names of the ip addresses you have connections to.  Without it, this command is so slow, it may appear broken.

Your should get one results like this.  

TCP    0.0.0.0:62646       D2000:0                LISTENING       2076

What your looking for is the number at the end of the line.  It’s the PID of the process that currently has the port open.

Use PS Kill

Once you know the PID of the process you need to kill you can use pskill to stop it. 

Open an administrative command prompt, then run pskill <pid> (in this example pskill 2076)

Note: On very rare occasions you will see a PID or 0 or 1 (I forget off the top of my head.  This is the NT system process.  I do not recommend trying to kill it)

Tips for Setting up SSAS Access over IIS/HTTP

One of what I think is a limiting factor for Analysis Services is its lack of a “standard” authentication mechanism.  There are lots of scenarios where windows authentication just isn’t practical.  Fortunately we can setup access to an SSAS server over HTTP with IIS and and ISAPI filter.  This MSDN article does a great job explaining the steps you need to take. 

https://msdn.microsoft.com/en-us/library/gg492140.aspx

We setup an IIS server running on Windows Server 2012 R2 connecting to SSAS 2014.  The only issue I found is during the connection testing phase.  Our excel test worked perfectly from outside our network but we kept getting the following error when connecting from C# using ADOMD. 

The integrated security ‘Basic’ is not supported for HTTP or HTTPS connections.

Now I just read in the article how basic authentication is supported so you can allow access from machines outside your network.  The good news is this isn’t referring to that basic authentication.  Here is the connection string recommended by the MSDN article.

Data Source=https://<servername>/olap/msmdpump.dll; Initial Catalog=AdventureWorksDW2012; Integrated Security=Basic; User ID=XXXX; Password=XXXXX;

The highlighted part is what’s causing the error.  Remove “Integrated Security=Basic;” and your connections should work fine.  We were able to connect over http, https, and by using a high number port above 5000 just by changing the IIS website bindings and the url in the connection string.  Overall I have been very happy with how this is working out.

Running Multiple Commented out SQL Queries at Once

So I do this a lot.  I have a couple of select statements that are commented out in my SQL script where I can check the outcome of some update or insert operation.  These statements are usually right above whatever script they are meant to verify.  Today I had two queries I wanted to run to see if the outcome was correct and I wanted them run at the same time.  I didn’t think this was possible, but it turns out it is.  Since the select statements are both commented out with – all you need is the first couple of characters of the queries removed and they can both run.  Square select is your friend here. It can select both lines at once without having to remove either of the comment marks and SQL management studio is smart enough to run just the selected parts of the queries even when the selection is through square select.  Here’s an example from the AdventureWorksDW database.

Square Select SQL Example

If you haven’t used square select, try it out.  Its great in all sorts of cases and works in SQL Management studio, Visual Studio and most great text editors including Notepad++.  Just hold down Alt+Windows Key and start making a selection. 

CSS Bundling the jQuery UI Theme

Its common in the projects I work on to have an images folder separate from the less/css folder.  When jQuery UI is used its usually got its own folder as well.  Here’s a sample with a number of things removed for clarity.

JQueryUI Solution Explorer Sample

In development while Bundling is turned off accessing an image in the menu.less file might look something like this. 

#contentContainer {
background: #FFFFFF url(‘../../images/masterPages/menu/contentContainerBackground.jpg’) no-repeat top center;
}

For context here is a sample bundle from our BundleConfig.cs

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles) {

        bundles.Add(new StyleBundle("~/cssBundles/masterPages/root").Include(
                    "~/css/masterPages/reset.css",
                    "~/jQueryUITheme/jquery-ui-theme.css",
                    "~/css/masterPages/root.css"
                    ));
    }
}

So its a happy accident this just works.  It turns out from the bundle path /cssBundles/masterPages if you go back two directories then you hit the root of the site and find the images directory.  The CSS works bundled and in development.  However, throw a jQuery UI theme in the middle of this and things aren’t so pretty.  jQuery by default keeps all its images in a subfolder next to the theme.  There really is no way to move the images around without editing the theme.css and since that file is generated I think its best to leave it alone.  So this left us in a odd spot because we wanted our theme to be bundled in with the rest of our css to keep down on the number of network requests, but we also didn’t want to try to move everything in the project around just to make bundling work.  So here’s our answer, URL Rewrite. As usual extra information removed for clarity.

<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Rewrite jQueryUI Images for Bundling">
                    <match url="cssBundles/masterPages/images/(.*)" />
                    <action type="Rewrite" url="jQueryUITheme/images/{R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

This catch all rule looks for images the jQuery UI theme thinks should be on the end of our bundle url and redirects them to where we want to keep them in the project.  It’s a little black magic, but its configure once and forget about it.  Now all our bundling works in dev and prod. 

Granting Execute Rights on Every Stored Procedure is a Pain

I did this again the other day when setting up a database so I thought I would share.  In SQL server its pretty easy to grant someone read access or write access to all the tables.  You just have to assign them the data_reader or data_writer database role.  Since most of the projects I work use a custom ORM that back ends into stored procedures I wanted the same simplicity of granting execute rights for all stored procs in the database.  I give you db_executor. 

/* CREATE A NEW ROLE */
CREATE ROLE db_executor

/* GRANT EXECUTE TO THE ROLE */
GRANT EXECUTE TO db_executor
Once you have run this in your database you can assign the role to any user who needs to execute all stored procs.  The nice part about this role compared to selecting all the stored procs and granting individual execute privilege to them as you add new stored procs the users in this role will automatically have rights to execute them. 

AngularJS Routing: Using Otherwise without redirectTo (or how to make a 404 page)

Every example I see of the otherwise statement in the built in AngularJS routing configuration looks like this.

var app = angular.module(‘myApp’, [‘ngRoute’]);

app.config(function ($routeProvider) {
$routeProvider
.when(‘/‘, {
controller: ‘HomeController’,
templateUrl: ‘Views/home.html’
})
//other whens removed
.otherwise({ redirectTo: ‘/‘ });
});

That’s nice, but what if I want to have a 404 page? At this moment the angular docs don’t give much of a hint to what is possible.

Angular Otherwise Documentation

I really wanted a default page that let the user know something went wrong instead of just sending them to the home page.  This turns out to be quite easy.  The example below loads it own Controller and View when no match is found.

var app = angular.module('myApp', ['ngRoute']);

app.config(function ($routeProvider) {
    $routeProvider
    .when('/', {
        controller: 'HomeController',
        templateUrl: 'Views/home.html'
    })
    //other whens removed
    .otherwise({
        controller: 'Error404Controller',
        templateUrl: 'Views/Error404.html'
    });
});

I suspect all the options for the $routeProvider work but these are all I have confirmation for.  Also, I am sure someone is thinking “this is not a real 404 page since the response code is not a 404.”  That’s ok with me.  I am still going to think of it as “Page Not Found”.

Memory Streams to Close() or Dispose()

I was at the .net users group meeting the other night and we were discussing code analysis.  Just for fun I ran it on the project I was working on that day and ran across this warning. 

Dispose Warning

Here is (basically) the code that was causing it.

Code Sample

I asked, why is this an issue?  A couple of comments.

  • Are you disposing of it in a using statement?
  • Are you doing this in a try block and disposing of it in both the try and the finally?

Neither of those is happening. 

The generally consensus was it should not do that because close never calls dispose, but after some research I see why it is.  Since code analysis works on the IL code it can see things we can’t see on the surface.  According to this answer on stack overflow the close method is calling dispose for you.  That’s handy right?  How about this from the MSDN documentation, emphasis mine.

Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. Instead of calling this method, ensure that the stream is properly disposed.

That seems reasonable, apart from having a public method I am told in the docs not to call.  Going too far the other way removing both the .Close() and .Dispose() leaves us with this message. 

No Dispose Warning

I am going to go with just .Dispose().  Today its not really different from calling both, but in the future it might be and the docs say to do it this way.  Plus, it gets rid of the nagging warning. 

Single Quotes/Ticks in Content-Disposition Header

We got a bug report on an website today that people could no longer open files we store in a SQL database.  After a little research we determined the issue was only in IE10 and IE11.  Here is what the download message looked like. 

Download Message

Notice the extra single ticks around motorists.jpg?  When you download a file and the extension is .jpg’ or .zip’ you get unpredictable results.  Here is the line of code that was causing the issue. 

Content Broken

Here is the fixed line of code.  Just removing the single ticks from around the file.

Content Fixed

二、感染丰胸产品。吸脂隆胸必须在无菌状态下进行丰胸成功案例,所有设备都应经过严格的消毒丰胸方法,如果术中消毒不严格,就容易导致感染丰胸食物