Donnerstag, 6. Februar 2025

Generate and Scan cryptographically signed QR Codes im Blazor

QR Codes are very common nowdays - they are so common that they are used to attack users by replacing the real QR Code with a manipulated version so the user comes to a phising site instead of the real site.

So, why not adding a digital signature to a QR Code to be sure about its origin and that it has not been tampered with? In this article I will show you all the basic building blocks you need to do this in Blazor. And because most of the code is acutally JavaScript, you will be able to use it in any SPA as well.

TL;DR

The code is on my GitHub.

Generating QR Codes

At first we need to be able to genereat QR Codes. For this we are using a QR Code Library. I have chosen QRious. The JavaScript code to generat a QR Code is:
var qrCode;

window.qrGenerator = {

    initializeQrCode: function (container) {
        var containerElement = document.getElementById(container);

        if (containerElement !== null && qrCode === undefined) {
            qrCode = new QRious({element: containerElement, size: 300});
        }
    },

    generateQrCode: function (data) {
        // stringify json the data
       const jsonData = JSON.stringify(data);
       qrCode.set({value: jsonData});
    },

    clearQrCode: function () {
        qrCode.set({value: ''});
    }

}
The initialize function takes the name of a container element which must be a canvas.Then a QRious object is created on that element. To generate a QR-Code we can call the set funtion and pass a value. In the code above we pass an object to the function that we turn into JSON before setting it to the QR Code.

On the Balzor end we need a way to call to the JavaScript, which is done via the IJSRuntime interface:

@page "/"
@inject IJSRuntime JS

<canvas id="qrcode" />

@code {
    override protected async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JS.InvokeVoidAsync("qrGenerator.initializeQrCode", "qrcode");
            await JS.InvokeAsync<string>("qrGenerator.generateQrCode", "Hello World!!");
        }
    }
}
 

Adding a cryptographic signature

The code to generate a public / private key pair is not C# but JavaScript again. I was hoping to be able to use C# for this in Blazor, but it turns out that the needed APIs are not supported in Blazor. So we have to fall back to the native JavaScript crypto.subtle APIs. These are low level cryptographic APIs which involve a high risk of getting things wrong, sacrificing any security. So make sure to check this with a security expert.

The code to generate a key pair is as follows.
window.cryptoHelper = {
    generateKeyPair: async function () {
        const keyPair = await window.crypto.subtle.generateKey(
            {
                name: "RSA-OAEP",
                modulusLength: 2048,
                publicExponent: new Uint8Array([1, 0, 1]),
                hash: "SHA-256"
            },
            true,
            ["encrypt", "decrypt"]
        );

        const publicKey = await window.crypto.subtle.exportKey("spki", keyPair.publicKey);
        const privateKey = await window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey);

        return {
            publicKey: btoa(String.fromCharCode(...new Uint8Array(publicKey))),
            privateKey: btoa(String.fromCharCode(...new Uint8Array(privateKey)))
        };
    }
}

The generateKey funciton is used, and the first parameter is the algorithm. RSA-OAEP generates an asymetric key pair. The function can also create symmetric keys. The second parameter tells the api that the key is exportable. And the third parameter tells us what we can do with the key, which is irellevant in the code above, because the key is not used, it is just exported. This is done by the exportKey function. The public and private key are exported in suitable formats (spki and pkcs8) and returned to the calling Blazor app as base64 encoded strings.

Calling this is done in the same way as above using the IJSRuntime.
public class KeyPair
{
    public string PublicKey { get; set; }
    public string PrivateKey { get; set; }
}

@page "/signaturePlayground"
@inject IJSRuntime JS

code {

    private async Task GenerateKeyPair(MouseEventArgs args)
    {
        var keyPair = await JS.InvokeAsync<KeyPair>("cryptoHelper.generateKeyPair");
    }

}

For signing and validating a signature the respecive key must be imported first: for signing we need the private key, for validation the public key:

const privateKey = await window.crypto.subtle.importKey(
    "pkcs8",
    Uint8Array.from(atob(privateKey), c => c.charCodeAt(0)),
    {
        name: "RSA-PSS",
        hash: { name: "SHA-256" }
    },
    false,
    ["sign"]
);


For the public key and the virification the code is basically the same, you just have to switch the format from pkcs8 to spki and the purpose of the imported key from sign to verify.

Siging is done by the sign function:

const signature = await window.crypto.subtle.sign(
    {
        name: "RSA-PSS",
        saltLength: 32
    },
    privateKey,
    new TextEncoder().encode(data)
);

And verification by the verify function:

const isValid = await window.crypto.subtle.verify(
    {
        name: "RSA-PSS",
        saltLength: 32
    },
    publicKey,
    Uint8Array.from(atob(signature), c => c.charCodeAt(0)),
    new TextEncoder().encode(data)
);


Scanning a QR Code

For scanning a QR Code I choose the nimic libarary. You need to download the qr-scanner-umd.min.js and the qr-scanner-worker.min.js, the latter one is a dependency to the first one.

Starting a scan needs a video element for the QrScanner class and a callback into Balzor which is called OnQrCodeScanned.

startScan: function (dotNetObject) {
    qrScanner = new QrScanner(
        document.getElementById("qrScanner"),
        result => {
            console.log('decoded qr code:', result)
            dotNetObject.invokeMethodAsync('OnQrCodeScanned', result.data);
        },
        {
            highlightScanRegion: true,
            highlightCodeOutline: true,
        },
    );
    qrScanner.start();
}

The dotNetObject being passed to the function allows the callback to Blazor. This has to be passed in from the Balzor side:


@page "/scanQrCode"
@inject IJSRuntime JS

<video id="qrScanner"></video>
<textarea @bind="qrCodeData"></textarea>

@code {
    private string qrCodeData = string.Empty;

    override protected async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JS.InvokeVoidAsync("qrScanHelper.startScan", DotNetObjectReference.Create(this));
        }
    }

    [JSInvokable]
    public async Task OnQrCodeScanned(string qrCodeData)
    {
        this.qrCodeData = qrCodeData;
        StateHasChanged();
    }
}


This is achived by the DotNetObjectReference.Create method that gets a reference to this, the object representing the page. By marking a method with the [JSInvokable] attribute Blazor knows that this method is allowed to be called from JavaScript.

Just glue it together

These are all the moving parts you need to add a digital signature to your QR Code and verify that you have a real QR code. Working code for all this is on my GitHub.







Mittwoch, 7. Februar 2018

Handling child collectins in EF (now Core) - Again

I hitted the same issue as described in a previous post once again. Last time it was EF6, this time EF Core.

It is about having a simple model with a parent entity having a collection of child entities like in

public class Basket
{
    public Guid Id { get; set; }
    public Guid CustomerId { get; set; }
    public virtual IList<BasketItem> Positions { get; set; }
}

public class BasketItem
{
    public int Id { get; set; }
    public string ArticleName { get; set; }
    public decimal Amount { get; set; }
    public decimal Price { get; set; }
}

public class BasketContext : DbContext
{
    public BasketContext() : base("BasketContext") 
    {
    }
    
    public DbSet<Basket> Baskets { get; set; }
}

Please notice that there are neither unecessary navigation properties nor unecessary DbSets in the context.

With EF6 we needed to override the OnSaveChanges method to handle the problem, but things got better with EF Core. While the default behaviour still is an optional relationship whose foreign key will be set null on the database, we can now configure the relationship to be required and cascade on delete like so:


protected override void OnModelCreating(ModelBuilder modelBuilder)
{
            
     modelBuilder.Entity()
                .HasOne(typeof(Basket))
                .WithMany(nameof(Basket.Positions))
                .IsRequired()
                .OnDelete(DeleteBehavior.Cascade);

     base.OnModelCreating(modelBuilder);
}

Thanks to EF core it is now possible to define one-to-many relationships without the need of an explicit navigation property just by giving it a type. The IsRequired call makes the FK-filed on the database non nullable and the delete behaviour yields to the deletion of the chilg, as described in the EF Core docs on the topic.

So while I still feel that the EF Core default is unatural, the possibilities to fix the error became much cleaner.

Sonntag, 19. November 2017

noderunner.exe is eating all your memory?

Just as a note to myself: if you have to work with sharepoint you might notice a very high memory consumption from several noderunner.exe-processes.

There alerady exists an explanation of how to reduce this, here are the crucial steps:


  • Open a Sharepoint Management Shell
  • Set-SPEnterpriseSearchService -PerformanceLevel Reduced
  • Get-SPEnterpriseSearchService
    Should show "Performance Level: Reduced" now
  • Open C:\Program Files\Microsoft Office Servers\15.0\Search\Runtime\1.0\noderunner.exe.config in Notepad
  • Update <nodeRunnerSettings memoryLimitMegabytes=”0″ /> to say 100
  • Restart SharePoint Search Host Controller Service

And you are done.


Dienstag, 24. Oktober 2017

.NET Core Web API: Returning a file from an OutputFormatter

Let's say you want to return a csv file from your web API. To return a file from a controller action is as easy as writing

return File(stream, "text/csv");

It is not that eays if you are using an output formatter to be able to return either json or a file from the same controller method based on the Accept header. Then your controller looks like this:

return Ok(data);

And you need to register your output formatter with MVC:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services
        .AddMvc(options =>
            {
                options.RespectBrowserAcceptHeader = true;
                options.OutputFormatters.Add(new CsvOutputFormatter());
            });
};

Within your formatter you need to render your data to Csv. You can easily use a NuGet package for this purpose. Writing the formatter is easy then:

public class ApetitoArticleCsvOutputFormatter : OutputFormatter
{

    public ApetitoArticleCsvOutputFormatter()
    {
        ContentType = "text/csv";
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
    }
    
    public string ContentType { get; private set; }

    public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
    {

        var articles = context.Object as IEnumerable<Article>;

        var response = context.HttpContext.Response;
        response.Headers.Add("Content-Disposition", "attachment; filename=export.csv");

        using (var writer = context.WriterFactory(response.Body, Encoding.UTF8))
        {
            var csv = new CsvWriter(writer);
            csv.WriteRecords(articles);

            await writer.FlushAsync();

            
        }
    }
    
}


You just get your data from context.Object, get the Repsones object and a writer to the body stream and let CsvHelper write your data to this stream. Usually you will get the data being send back as text, for example when using swagger. But we want to make the browser save a file from the csv we requested.

The bold line does the trick: simply add a Content-Disposition header with value attachment and the name of you file. Now the browser saves the file, or swagger shows you a link to start the download.


Dienstag, 4. April 2017

Team Build with Remote Powershell Cross Domain

I ran into a series of issues when trying to establish a release pipeline in TFS where the build agent is located in the company domain whereas the target server is inside a DMZ-domain. I tried to run the "Run Powershell on Remote Machine" from the company domain build agent computer with a target machine located in the DMZ domain. I do not memorize all the errors I got in detail, but they were all around "WinRM, Could not process request, Kerboros, No authentication Server, Host not found".

Basically the problem comes down to open a remote powershell session. So if this succeeds when logged in to the company domain build agent computer and you connect to srv.mydmz.de being the target server in the dmz-domain:

Enter-PSSession 
    -ComputerName "srv.mydmz.de" 
    -Credential mydmz\username

then your build / release Task "Run Powershell on Remote Machine" should succeed as well. This is useful for testing purposes because you do not need to create a release definition upfront and create a release every time you try to get things up and running.

I found the steps to solve my problem in a blog post from Christopher Hunt, but I want to stress out on thing that I got wrong from many other blog posts providing the same solution.

The solution is rather simple. On the build agent computer and on the target DMZ computer run: 

WinRM Quickconfig 

Then, log in to the build agent computer and run this from an elevated command prompt:

Set-Item wsman:\localhost\Client\TrustedHosts -value "srv.mydmz.de" 

This adds the target server located in the DMZ as trusted host on the company domain joined build agent computer. Then the above command to open a remote powershell succeeded for me where it formerly failed. So a release definition like this should work then if the build agent computer is configured as stated above:

Release Definition executing a powershell across domains


So, call me dumb, but here is the thing I always got wrong until now: you have to add the DMZ-Server as trusted host on the company domain joined server, not the other way round.

To me it appeared more logical that the computer being called (the DMZ-server), i. e. where the remote powershell executes stuff, should trust the computer calling it (the company domain joined server). So I repeatedly tried the Set-Item-Command on the DMZ-Server setting the domain joined build agent computer as the trusted host.

Now that my incompetence in this case is revealed, maybe it might save others some time :-)

Montag, 23. Januar 2017

Handling child collectins in Entity Framework Code First

There are a lot of blog posts out there on the issue of removing items from child collections in Entity Framework.

The Problem

The Problem is, that when you remove an item from a child collection of an entity, EF just sets the foreign key null in the child collections table. It does not delete the item. While this means that the item does no longer appear in your collection, it is not a satisfying situation as it leaves orphaned records around.

Possible solutions and problems with the solutions

There are three possible solutions to the problem:
  1. Explicitly remove the child
  2. Identifying Relationships
  3. SaveChanges
The first one means, that whenever you remove something from a child collection you remove it from the according DbSet-Property of your context as well. This is obviously a bad design, becaus for child collection I do not want a DbSet collection of its own.
The second one means that you need to make the primary key of the parent part of the primary key of the child. This is bad because I need to change my model and bloat it with unnecessary properties - even worse these properties merely contain technical database stuff.  
The third one comes close to a good solution, but not the way I like to handle it. It requires to override the SaveChanges method of the context and handle deleting orphans there. This is the best solution so far because it tackles the problem close to its origin: inside the technical EF code stuff. But almost any implementations on the web tend to do it in a way that comes close to solution 2: the have kind of a navigation propertey in the child that points to the parent and that can be checked for null. Others suggest using domain events, which is generally a great concept but it feels weired to introduce it to solve a infrastructural problem.

My context

So here is my context, the scenario was from a coding dojo we did. It is a very database focused and very simplified implementation of a shopping cart:

public class Basket
{
    public Guid Id { get; set; }
    public Guid CustomerId { get; set; }
    public virtual IList<BasketItem> Positions { get; set; }
}

public class BasketItem
{
    public int Id { get; set; }
    public string ArticleName { get; set; }
    public decimal Amount { get; set; }
    public decimal Price { get; set; }
}

public class BasketContext : DbContext
{
    public BasketContext() : base("BasketContext") 
    {
    }
    
    public DbSet<Basket> Baskets { get; set; }
}

That is it. You see that Basket has a Guid-Id while BasketItem has an int-Id. This reflects the fact that I consider Basket to be an Aggregate Root on the level of my domain model, while Basket Item is just a contained entity, that does not have an id that is relevant outside of its containing basket. The need for the id is just for the sake of a relational database.
So, when searching for a solution to my problem, I made the following premise, stated loud and clear:
"I will try as hard as I can (very very hard) to never change my model just for the sake of a relational database!"
Having said that, all solutions I found on the web are not for me. Because as my requirements were, my model has no need for a Basket property, or even worse a BasketId property, on the BasketItem. This renders the above options 2 and 3 useless. Option 1 is useless as it requires me to add a DbSet for BasketItems, which is not necessary as they dont get queried directly.

My (prototype) solution

The following solution is not production ready. It is the solution I found in a late-at-the-day hacking session after the dojo that brought the problem to the surface. It ignores edge cases. It is not tested well. Keep that in mind, and dont say I did not warn you.
The solution follows pattern number three from the above solutions, overriding SaveChanges(). But it does not require to fiddle around with your model. My idea was: if EF knows that it has to set a value in table to null, it must be able to find out for me as well.

public override int SaveChanges()
{
    var objectContext = ((IObjectContextAdapter) this).ObjectContext;
    
    objectContext.DetectChanges();

    var deletedThings =
        objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted).ToList();

   
    foreach (var  deletedThing in deletedThings)
    {
        if (deletedThing.IsRelationship)
        {
            var deletedKey = deletedThing.OriginalValues[1] as EntityKey;
            var entityToDelete = objectContext.GetObjectByKey(deletedKey);
            objectContext.DeleteObject(entityToDelete);
        }
    }

    return base.SaveChanges();
}

This can not be done using the DbContext-Api, but needs to be done with the ObjectContext-Api, so we have to obtain it using the IObjectContextAdapter interface. We need to call DetectChanges, otherwise the deletedThings are empty. In case of an orphaned child entry, the deletedThings contain entries for relationships (deletedThing.IsRelationship yields true). In that case we can find the ends of the relationship in the OriginalValues. A two element array where index 0 points to the parent (the basekt in the example) and index 1 points to the child (the BasketItem). By "points to" I mean that the OriginalValues contains an EntityKey-object identifying the object in question. So using GetObjectByKey(deletedKey) we can load the orpahned child. We must delete it using DeleteObject(entityToDelete) because there is no explicit EntitySet holding it.

I hope someone might find it useful.

Dienstag, 3. Januar 2017

Performance Profiling WCF Service running in WCF Test Client

I know the topic itself sounds a bit old school, but despite what many of my colleagues say, I think WCF is still alive and you might encounter it along your way. Furthermore I found it surprisingly hard to get the configration right to use Visual Studio Performance Profiling on a WCF Service that is running in the WCF Test Client - and is therefore not (yet) deployed to IIS. I mean the kind of WCF Application that you can start by simply hitting F5 and get going using the test client.

So as a note to myselft and hopefully as a help for someone else, here ist how I did it.

Choose Analyze | Performance Profiler (Alt + F2 using the standard shortcuts). Then go through the Performance Wizard.

Page 1 of 4: Specify the profiling method

Choose Instrumentation.

Page 2 of 4: Choose the modules to profile using the instrumentation method

Choose One or more available projects and select the WCF Service Project.

Page 3 of 4: These are things you may want to specify about the non-launchable project(s) you are going to profile

This is the tricky one. The thing is, to use the test client you must not start the test client. You must start the WCF Test Service Host. So set the Executeable path to

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfSvcHost.exe

Modyfiy the path as needed for your Visual Studio version. As Command-line arguments pass the following:

/service:<YourServiceProjectName>.dll /config:<YourServiceProjectName>.dll.config

Fill in the the name of your service project appropriately. The name of the config file points to the app.config file in your project, which is being renamed during compilation. As Working directory set

C:\<Path to my service library project>\bin\Debug\

Page 4 of 4: You have completed specifying settings for your new performance session

You might probably want to uncheck the Launch profiling after the wizard finishes checkbox to check the settings that have been created.

Tweaking the settings

Now your performance Wizard should look like this. That was not the final soultion for me, I needed to further tweak these settings.

Figure 1: The performance profiler after finishing the wizard

So, open the properties of your service project node. On the launch tab check Override project settings and repeat the settings you did before:
Executable to launch: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfSvcHost.exe 
Arguments: /service:<YourServiceProjectName>.dll /config:<YourServiceProjectName>.dll.config
Working Directory: C:\<Path to my service library project>\bin\Debug\

Then delete the second node. You might as well delete the first node and rename the second. Maybe the intial version works too, but I ended up with this after running a profiling session:

Figure 2: The final performance profiler after running a session

For the records, here is the content of my .psess file, of course names and Guids will differ in your file, but sometimes it helps to have just the bits:

<?xml version="1.0" encoding="UTF-8"?>
<VSPerformanceSession Version="1.00">
  <Options>
    <Solution>WCFServices.sln</Solution>
    <CollectionMethod>Instrumentation</CollectionMethod>
    <AllocationMethod>None</AllocationMethod>
    <AddReport>true</AddReport>
    <ResourceBasedAnalysisSelected>true</ResourceBasedAnalysisSelected>
    <UniqueReport>Timestamp</UniqueReport>
    <SamplingMethod>Cycles</SamplingMethod>
    <CycleCount>10000000</CycleCount>
    <PageFaultCount>10</PageFaultCount>
    <SysCallCount>10</SysCallCount>
    <SamplingCounter Name="" ReloadValue="00000000000f4240" DisplayName="" />
    <RelocateBinaries>false</RelocateBinaries>
    <HardwareCounters EnableHWCounters="false" />
    <EtwSettings />
    <PdhSettings>
      <PdhCountersEnabled>false</PdhCountersEnabled>
      <PdhCountersRate>500</PdhCountersRate>
      <PdhCounters>
        <PdhCounter>\Arbeitsspeicher\Seiten/s</PdhCounter>
        <PdhCounter>\Physikalischer Datentr&amp;amp;amp;amp;amp;#228;ger(_Total)\Durchschnittl. Warteschlangenl&amp;amp;amp;amp;amp;#228;nge des Datentr&amp;amp;amp;amp;amp;#228;gers</PdhCounter>
        <PdhCounter>\Prozessor(_Total)\Prozessorzeit (%)</PdhCounter>
      </PdhCounters>
    </PdhSettings>
  </Options>
  <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
  <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
  <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
  <PreinstrumentEvent>
    <InstrEventExclude>false</InstrEventExclude>
  </PreinstrumentEvent>
  <PostinstrumentEvent>
    <InstrEventExclude>false</InstrEventExclude>
  </PostinstrumentEvent>
  <Binaries>
    <ProjBinary>
      <Path>WCFServices\obj\Debug\WCFServices.dll</Path>
      <ArgumentTimestamp>01/01/0001 00:00:00</ArgumentTimestamp>
      <Instrument>true</Instrument>
      <Sample>true</Sample>
      <ExternalWebsite>false</ExternalWebsite>
      <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
      <IsLocalJavascript>false</IsLocalJavascript>
      <IsWindowsStoreApp>false</IsWindowsStoreApp>
      <IsWWA>false</IsWWA>
      <LaunchProject>false</LaunchProject>
      <OverrideProjectSettings>true</OverrideProjectSettings>
      <LaunchMethod>Executable</LaunchMethod>
      <ExecutablePath>C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfSvcHost.exe</ExecutablePath>
      <StartupDirectory>WCFServices\bin\Debug\</StartupDirectory>
      <Arguments>/service:WCFServices.dll /config:WCFServices.dll.config</Arguments>
      <NetAppHost>IIS</NetAppHost>
      <NetBrowser>InternetExplorer</NetBrowser>
      <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
      <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
      <PreinstrumentEvent>
        <InstrEventExclude>false</InstrEventExclude>
      </PreinstrumentEvent>
      <PostinstrumentEvent>
        <InstrEventExclude>false</InstrEventExclude>
      </PostinstrumentEvent>
      <ProjRef>{582C5667-EF99-4934-BD8C-938E75803D39}|WCFServices\WCFServices.csproj</ProjRef>
      <ProjPath>WCFServices\WCFServices.csproj</ProjPath>
      <ProjName>WCFServices</ProjName>
    </ProjBinary>
  </Binaries>
  <Reports>
    <Report>
      <Path>WcfSvcHost160926.vsp</Path>
    </Report>
    <Report>
      <Path>WcfSvcHost160927.vsp</Path>
    </Report>
  </Reports>
  <Launches>
    <ProjBinary>
      <Path>:PB:{582C5667-EF99-4934-BD8C-938E75803D39}|WCFServices\WCFServices.csproj</Path>
    </ProjBinary>
  </Launches>
</VSPerformanceSession>


So, this is it. Now you should be able to find your performance bottleneck in your WCF Code!




Freitag, 6. Mai 2016

A JSON to JSON Template Engine

I came across a feature request, where it was needed to have a command line tool that is able to send variours JSON messages over the wire. Think of a JSON structure that represents the message template and that must be filled with different data values every time you want to send a message. Because the message template and the data are passed as JSON strings to the command line tool, all of this is not strongly typed but rather JSON strings.

So I thought of having a JSON structure that is a template having placeholders. These placeholders need to be filled with concrete values from a second JSON object. I thouht of a format for the placeholders and decided that it would be best if the placeholders are defined as valid JSON as well, so I can parse them easily.

Think of the following example:

{
    "Salution": <Fill from data field Contact.Salutation, if this is not present leave it null>,
    "FirstName": <Fill from data field Contact.FirstName>,
    "LastName": <Fill from data field Contact.LastName>,
    "Sex": <Fill from data filed Contact.Sex, if this is not present fill with value 'No information'>,
    "IsConfirmed": <Fill from data field IsConfirmed>
    "MessageType":"NewContactAdded",
    "Metadata" :
    {
        "CreatedOn": <Generate DateTime.Now>,
        "CreatedBy": <Fill from data field User>,
        "CorrelationId": <Generate Guid.NewGuid()>
    }
}

As a template this looks like this:

{
    "Salution":{ "Path":"Contact.Salutation", "Optional":"true" },
    "FirstName": { "Path":"Contact.FirstName" },
    "LastName": { "Path":"Contact.LastName" },
    "Sex": { "Path":"Contact.Sex", "Or":{ "Expression":"No information" } },
    "IsConfirmed": { "Path":"IsConfirmed" }
    "MessageType":"NewContactAdded",
    "Metadata" :
    {
        "CreatedOn": { "Expression":"DateTime.Now" },
        "CreatedBy": { "Path":"User" },
        "CorrelationId": { "Expression":"Guid.NewGuid()" }
    }
}

Given the following data

{
    "User":"trichling",
    "IsConfirmed":"true",
    "Contact":
    {
        "FirstName":"Peter",
        "LastName":"Pingel"
    }
}

will expand to

{
  "Salution": null,
  "FirstName": "Peter",
  "LastName": "Pingel",
  "Sex": "No information",
  "IsConfirmed": "true",
  "MessageType": "NewContactAdded",
  "Metadata": {
    "CreatedOn": "2016-05-06T12:17:17.9187797+02:00",
    "CreatedBy": "trichling",
    "CorrelationId": "2c59a1ee-be98-43b8-a046-d9ecb20a33aa"
  }
}

The Salutation was omitted in the data, but it is marked as optional, so a missing value will be ignored. First- and LastName are filled from a nested object in the data structure. The property Sex is also omitted, hence the default expression defined in the Or-part of the placeholder is used. The MessageType is a constant string, so it will be added as is to the output. The Metadata complex property is made up of a timestamp which is generated via an expression placeholder, as well as the CorrelationId.

Is this even useful? Can anyone think of different / broader use cases for this? Does anyone know a solution to the problem that already exists? I have searched the web but i could not find anything. That made me wonder: am I really the first person who thought about this (which I consider very unlikely), or does the whole use case make no sense?

I implemented a working solution that at least served my needs. Might anyone else feel this is useful? Please enlight me :)

If someone is interested, I am happy to share the source code - if not, I will hide in shame :)


Freitag, 8. April 2016

Manage Views with EF Code First + Migration Support

I had to search around for a while to find a solution to the problem of adding a view to an Entity Framework Code First Context. I wanted my solution to work with a view that does not yet exist. The view must be created (and removed if necessary) by a migration. I am fine with the fact that the view has the same name as the property in the context.

You can find an explanation about how to use pre-existing views in a context, as well as ideas on how to add a view via migrations. What was missing for me was a complete example that combines both aspects. So here is mine :-)

We start with a simple User class,

public class User
{
    public Guid Id { get; set; }
    public string Login { get; set; }
    public bool IsAdmin { get; set; }
}

and add this to a very simple context

public class ViewContext : DbContext
{

    public ViewContext()
        : base("ViewContext")
    {

    }
    
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasKey(u => u.Id)
            .Property(u => u.Id)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        base.OnModelCreating(modelBuilder);
    }
}

Using the Package Manager Console we enable migrations and create an initial migration and apply it to the database:

enable-migrations
add-migration initial
update-database

Now I want to create two views, one that filters on admin users and the other that filters on normal users.

The first thing to to is, to create a new class that reflects the view to be created, adding a DbSet using that class to the context and create a migration for it.

public class AdminUser
{
    public Guid Id { get; set; }
    public string Login { get; set; }
}

public class ViewContext : DbContext
{
    public DbSet<AdminUser> AdminUsers { get; set; }
}

add-migration viewadminusers

The migration created after this change contains a CreateTable-Statement. This is not the desired thing to happen, so this has to be changed. It is possible to use the DbMigrations Sql-Method for this an pass in the SQL as a string. This is an easy solution, but it did not satisfy me. I wanted a solution that looks more like native migrations, like so:

public partial class viewadminusers : DbMigration
{
    public override void Up()
    {
        CreateView("dbo.AdminUsers", "SELECT * FROM Users WHERE IsAdmin = 1");
    }
    
    public override void Down()
    {
        DropView("dbo.AdminUsers");
    }
}


So I digged a little deeper, and found an approach to add new operations to DbMigrations. The example shows how to add check constraints, and it works all the same for views.

First of all we need a POCO class to describe our operation:

public class CreateViewOperation : MigrationOperation
{

    public CreateViewOperation(string name, string sql)
        : base(null)
    {
        this.Name = name;
        this.Sql = sql;
    }

    public string Name { get; set; }
    public string Sql { get; set; }

    public override bool IsDestructiveChange
    {
        get
        {
            return false;
        }
    }
}

The class must derive from MigrationOperation and holds properties for the name and the SQL-Body of the view. To be able to use this Operation in a Migration, we can use extension methods on DbMigration:

public static class CreateViewExtension
{
    public static void CreateView(this DbMigration migration, string name, string sql)
    {
        var createViewOperation = new CreateViewOperation(name, sql);
        ((IDbMigration)migration).AddOperation(createViewOperation);
    }

    public static void DropView(this DbMigration migration, string name)
    {
        var dropViewOperation = new DropViewOperation(name);
        ((IDbMigration)migration).AddOperation(dropViewOperation);
    }
}

With this code in place we can write the migration almost like stated in the above example, the only difference is that one must use the this-prefix in front of the method name which is close enough.

this.CreateView("dbo.AdminUsers", "SELECT * FROM Users WHERE IsAdmin = 1");

The thing that acutally translate the operation to SQL is a subclass of SqlServerMigrationSqlGenerator:

public class CustomSqlServerMigrationGenerator : SqlServerMigrationSqlGenerator
{
    protected override void Generate(MigrationOperation migrationOperation)
    {
        if (migrationOperation is CreateViewOperation)
        { 
            Generate(migrationOperation as CreateViewOperation);
            return;
        }

        base.Generate(migrationOperation);
    }

    protected virtual void Generate(CreateViewOperation createViewOperation)
    {
        using (var writer = Writer())
        {
            writer.WriteLine(
                "EXEC ('CREATE View {0} AS {1}')",
                Name(createViewOperation.Name),
                createViewOperation.Sql
            );
            Statement(writer);
        }
    }
}

The override of the general Generate(MigrationOperation) method checks if the operation is of type CreateViewOperation and hands over to the specialized Generate(CreateViewOperation) method. This method generates the SQL code using a special TextWriter and adds the resulting SQL using the Statement method.

Almost done! The only piece left is to add this SQL-Generator to the migrations configuration.

internal sealed class Configuration : DbMigrationsConfiguration<EFCodeFirstViews.ViewContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        SetSqlGenerator("System.Data.SqlClient", new CustomSqlServerMigrationGenerator());
    }
}

The SetSqlGenerator method of the DbMigrationsConfigurationType lets you add a SQL generator per provider type.

And this is it. The only thing that has to be done manually is to change the generated migrations file to use the CreateView method instead of create table.

Happy viewing!




Mittwoch, 16. Juli 2014

Die mystische CRUD 3 Schicht Architektur auf der DWX 2014


"Ist nur eine ganz kleine Applikation, eigentlich reines CRUD". Diesen oder ähnliche Sätze hat wohl jeder Entwickler schon mal gehört und vielleicht sogar einmal geglaubt. Später stellt sich dann heraus, dass ja doch etwas mehr zu tun ist... Die Session zeigt auf, wohin einen der CRUD Ansatz führt. In einem Rundflug über Architekturansätze a la DDD, CQRS und Co. werden Auswege aus dem Schlamassel aufgezeigt.
Hier geht es zu den Solides und Demos.

CEP & EDA auf der DWX 2014


Event Sourcing ist zum Buzzword avanciert. Warum nicht einen Schritt weiter gehen, und Events direkt zum Herzen der Anwendung machen? Hier kommt die Event Driven Architecture ins Spiel. Viele Geschäftsprobleme lassen sich als Strom von Ereignissen darstellen. Gerade wenn der Strom der Ereignisse umfangreich und stetig ist und Auswertungen in Echtzeit erfolgen sollen, kommen die Stärken dieses Architekturansatzes zum Tragen. Die Session zeigt Szenarien auf in denen EDA erfolgversprechend ist und illustriert diese Anhand eines praktischen Beispiels.


Hier gibt es die Solides und Demos.

Dienstag, 3. Dezember 2013

Get all changesets contained in a merge operation

When merging changes from one TFS branch to another, you can select to merge all changes up to a specific Version, or you can perform a chery pick merge. The latter means, that you pick the changesets you want to merge manually, which allows you to pick a not coherent sequence of changesets for merge.

If you want to know, given a changeset number representing a changeset that contains merges, changes from which changesets are included, afaik you need to aks the TFS API. To make life easier for you, here is my solution:


var tfs = new TfsTeamProjectCollection(new Uri("http://yourServer:8080/tfs/DefaultCollection"));
tfs.EnsureAuthenticated();
var versionControl = tfs.GetService<VersionControlServer>();

var changeSet = versionControl.GetChangeset(3894);
var mergeParentChangesets = changeSet.Changes
                                        .SelectMany(c => versionControl.QueryMergeRelationships(c.Item.ServerItem))
                                        .Select(i => i.Version)
                                        .Cast<ChangesetVersionSpec>()
                                        .Select(i => i.ChangesetId)
                                        .Distinct();


Here my changeset number is 3894. I iterate over all the changes in the changeset, asking for the merge relationships of each Change. I have to use SelectMany as QueryMergeRelationships returns an array of VersionSpec instances. Indeed, all these instances are truely ChangesetsVersionSpec objects, hence the cast. The latter object exposes the changeset id that we can collect in a distinct list.

Hope this helps, and happy merging!

Dienstag, 1. Oktober 2013

BASTA 2013 Follow Up

Auf der diesjährigen BASTA durfte ich unter dem Titel "Talk to my TFS" zum Thema TFS-API sprechen.

Folien und Demos zum Vortrag stehen jetzt zum download bereit.

Fragen und Kommentare zum Vortrag nehme ich gerne entgegen!

Viel Spaß mit dem Demos und dem TFS!

Donnerstag, 22. August 2013

Getting WebDeploy to work with Team Build with VS2012 & TFS2012

Lately I could finally make WebDeploy work from our Team build, deploying a WebSite that uses EF Code first as a database.

There is a lot of confusing stuff out there regarding this issue, and it took me some time to put all the pieces together to make it finally work.

That's why I am adding my own five Cents to it, as well as for having a reference if I ever have to do this again.

My Setup

Before going into detail on my solution, here is my Setup:
  • Two VS 2012 web-Solutions: one MVC WebApi Hosting a Service layer, and one vanilla ASP.NET Website using AngularJs for the Client. The former one was using an EF Code first model to store it's data and to run queries.
  • A Team build to be performed on an TFS 2012 Server, the build Agent running on the target web Server.
  • A web Server running IIS7 on a Windows Server 2012 machine

Install WebDeploy

The first step is to install WebDeploy on the target Server. On the web you find that using WebDeploy is different on IIS6 and IIS7 (Tory Hunts bolg entry was a good reference for that). IIS6 uses the "Web Deployment Agent Service" while IIS7 uses "Web Management Service".

It turned out, that with VS2012 you can use either way if you have IIS7 as in my case. I could not get the Web Management Service method to work, so I got along with Web Deployment Agent Service, which requieres a Admin-User to do the deployment. Due to the fact that the target Server was on our own Network, this was not a Problem for me.

The easiest way to install web deploy is using the Web Platform Installer. Under the Products-Tab search for web deploy and install "Web Deploy 3.5".



Installing Web Deploy using WebPI
The installer should configure the Firewall accordingly by adding a rule called "WdeployAgent" allowing incoming Connections on TCP Port 80. It also started the "Webbereitstellungs-Agent-Dienst" for me, which according to web sources you should not take for granted - so better double check.

Deploying a solution from Visual Studio

Next I tried to deploy a solution using Visual Studio. To do that, you need to create the target Website on the IIS of the target Server. I created a new Website that contains two applications: api and Client, one for the MVC WebApi Project and one for the Client.
IIS configuration on the target IIS
I started to deploy the Client Project, as it needed no database and so I thought it was easier to do. To publish a Project using VS2012 right-click the Project node and select "Publish". This fires up a Dialog that was different to all descriptions I found on the web, because they mostly referred to VS2010. On MSDN there is a nice Explanation of all the Settings that can be made.

You can create multiple publish profiles there. The most important Settings site is the "Connection"-Tab. The publish method of choice is "Web Deploy", which means you want to use either the Agent Service or the Management Serivce. Which one is acutally choosen depends on the Service Url you enter. According to MSDN, if you use http://machineName , the Agent Service is used. If your URL starts with https it should use the Management Service - but as I said, I could not get this one to work for me.
As Site/application I specified to use the IIS site and application that I have formerly created. The UserName / Password must be the built-in local Administrator account of the deployment machine (or a Domain admin account, which did not work for me). It is documented that a different user that has Administrator privileges will NOT work. If you tick the Save Password box, the Password will be saved encrypted in an local Settings file.
Visual Studio Deployment Settings
If you hit Validate Connection and everything is properly configured, you should get a green tickmark indicating that the Connection to the Agent Service can be established. Otherwise you get a more or less cryptic error message which are more or less well documented.
If you get the green tickmark, you can rush through the next steps of the wizzard without any further Action, or you just hit Publish. This Triggers a VS build and should publish your solution to the target server.

The Information you entered to the wizzard are being stored in your Project in the Properties Folder. There is a Sub Folder named PublishProfiles that contains a .pubxml File for each Profile. Alongside, but not shown in VS by Default, is a .pubxml.user file for each Profile, which contains the encrypted Password, in case you ticked the Save Password box. We Need to Change the .pubxml file later on, so it is good to know where it resides.

Integration with Team build

So far, this was quite easy and I was in a good mood to just integrate this with my Team build. To do this, you first Need to Setup a Team build for your solution. I skip that part here, as it is not the scope of this post. Given you have a Team build, you Need to tell it that it should deploy your solution(s). On the web you find the solution to add bunch of MSBuild-Parameters at the Process-Tab of the build Definition. This seemed to be messy to me, and you are totally lost if you want to publish more than one Project in one build.
I wanted to use the publish Profile I formerly created to be used by my Team build. That way I don't Need to maintain the Information more than once. After crawling the web for a while Scott Hanselmans blog post put me back on track: you can specify a PublishProfile Parameter for MSBuild to tell it to use the .pubxml-File. For being able to publish multiple Websites, you must not pass this as a Parameter to MSBuild using the build Definition, but you must incorporate the Switches in the .csproj file.
To do so, right click the Project and select "Unload Project" and then "Edit .csproj" from the context menu. Add the following snippet to the Project file:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DeployOnBuild>True</DeployOnBuild>
    <PublishProfile>pos.client.deploy.pubxml</PublishProfile>
  </PropertyGroup>

The condition ensures, that the Publishing only takes place for release builds. The DeployOnBuild Switch activates the deployment, and the PublishProfile Parameter Points to your publish Settings. So far you will Encounter a "USER_NOT_ADMIN" error from WebDeploy. This is due to the fact, that the .pubxml file does not contain the Password for the supplied Administrator user. This is stored in the .pubxml.user file, which is not added to source control. So in order to make things go right, you must manually edit the .pubxml-File and include the Password. My file Looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <CreatePackageOnPublish>True</CreatePackageOnPublish>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <SiteUrlToLaunchAfterPublish />
    <MSDeployServiceURL>http://machineName</MSDeployServiceURL>
    <DeployIisAppPath>posDeploy/client</DeployIisAppPath>
    <RemoteSitePhysicalPath />
    <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
    <MSDeployPublishMethod>RemoteAgent</MSDeployPublishMethod>
    <UserName>machineName\administrator</UserName>
    
    <Password>yourSecretPassword</Password>
    
    <PublishDatabaseSettings>
      <Objects xmlns="" />
    </PublishDatabaseSettings>
  </PropertyGroup>
</Project>

The CreatePackageOnPublish-Parameter yields to the creation of a WebDeploy package along with the deployment itself. It is located in the build drop Folder under _PublishedWebsites\YourProject_Package Folder and helps to Keep track of what was acutally published. Please notice the Password-Parameter, that mus contain the Password for the given built-in Administrator account for the deployment machine.

So far, so good...

Up to this Point, you should be able to Queue up your Team build and see your Website published to the target IIS Server.

In the next blog post, I will talk about how to get your EF code first database deployed during the Publishing process.



Donnerstag, 2. Mai 2013

A nice new feature for your ViewModel base class

Back in June 2010 I blogged about a View Model base class for WPF and Silverlight. With slight modifications I still use it today when I have to deal with MVVM.

With .NET 4.5 however, Microsoft added an new feature to the .NET Framework, that can make writing View Models even sweeter: the [CallerMemeberName]-Attribute.

Just a short recall: the view model base class uses two Methods Get and Set to manage property values. In your view model you can write something like

public class MyViewModel : ViewModelBase
{

  public string Name
  {
    get { return Get(() => Name); }
    set { Set(() => Name, value); }
  }

}

This way you get strongly typed properties in your view model, but you get rid of the backing field. And the base class takes care about change notifications via INotifyPropertyChanged. But to many people the lambda expression () => Name was confusing and hard to understand.Would it not be sweet if we could derive the calling property name from the context?

This was possible ever since by using the StackFrame class like this:

var stackTrace = new StackTrace();
var frame = stackTrace.GetFrame(1);
var callerName = frame.GetMethod().Name;

But this approach seems a bit cumbersome and has performance penalties, becuase building up the stack trace is an expensive operation. And for a property setter the the delivered method name is like "set_propertyName" - so additional work is needed to fiddle out the pure method name.

Thing get more handy with the new [CallerMemeberName] attribute. You can place it on a methods string parameter and this parameter will be filled with the name of the caller. Bummer. So your OnPropertyChanged-Method can look like this:

protected void RaiseNotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
  if (PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

This can be incorporated easily in our view model base class. It will look like this (a lot of stuff is ommited for brevity):

public class ViewModelBase : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  private Dictionary<string, object> _value = new Dictionary<string, object>(); 

  protected T Get<T>([CallerMemberName] string callerMemberName = "")
  {
    if (!_value.ContainsKey(callerMemberName))
      return default(T);

    return (T)_value[callerMemberName];
  }

  protected void Set<T>(T value, [CallerMemberName] string callerMemberName = "")
  {
    if (!_value.ContainsKey(callerMemberName))
      _value.Add(callerMemberName, value);

      _value[callerMemberName] = value;

    RaiseNotifyPropertyChanged(callerMemberName);
  }

  protected virtual void RaiseNotifyPropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }
}

We still have our methods Get / Set around, but they get an additional optional parameter for the caller member name. With this at hand, our above property example looks like this:

public class MyViewModel : ViewModelBase
{

  public string Name
  {
    get { return Get<string>(); }
    set { Set(value); }
  }

}

The one thing to do now, is explicitly stating the return type in the Get()-Method, because it can no longer be derived from the lambda expression. But you never get anything for free, right? Another downside is, that the attribute is not available in Silverlight.

It's a kind of magic - impress your colleagues with this one :-)