Contents tagged with .NET

  • Build and Debug ASP.NET MVC 5 Framework Web Application 4.x in VS Code

    Some of us are stuck with older, brownfield web projects based on Framwork 4.x that has to be supported yet for a while. But we’ve also tasted the sweetness of the still not bloated (dream on suckers, it will be bloated) VS Code and want to use it while it’s still pristine and fast. But is it possible?

    Yes, it’s possible

    It requires some editing with the launch.json and tasks.json files in the .vscode folder. Hang on and note that I just got this running last night.

    Fist, open the folder where your “old” web application is located. In the same directory as your .sln file, create a folder named .vscode. In the .vscode folder, a file called tasks.json, which describes one or more build steps.

    tasks.json

    {

        "version": "2.0.0",

        "tasks": [

            {

                "label": "build",

                "type": "shell",

                "command": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\MSBuild\\Current\\Bin\\msbuild.exe",

                "args": [

                    "${workspaceFolder}/WebApplication1/WebApplication1.csproj",

                    "/t:build",

                    "/p:GenerateFullPaths=true",

                    "/p:Configuration=Debug",

                    "/consoleloggerparameters:NoSummary"

                ],

                "group": {

                    "kind": "build",

                    "isDefault": true

                }

                "presentation": {

                    "reveal": "silent"

                },

                "problemMatcher": "$msCompile"

            },

        ]

    }


    Of course, you will have to replace “WebApplication1” with your project name, and you may also have to change the path to which ever msbuild.exe you want or need to run (bold, italic above).

    To build i VS Code, press CTRL+SHIFT+B and your project should do just that. The task we defined is set to be the default, so VS Code will not ask you for anything, just build. Hopefully.

    Run in IIS Express, 64-bit

    To run this application in IIS Express, add the following task to tasks.json “tasks” array:

    tasks.json (part)

            … stuff before…

            {

                "label": "iisexpress",

                "type": "shell",

                "command": "C:\\Program Files\\IIS Express\\iisexpress.exe",

                "args": [

                    "/path:${workspaceRoot}\\WebApplication1",

                    "/port:5006"

                ],

                "presentation": {

                    "reveal": "silent"

                },

                "problemMatcher": "$msCompile"

            },
           …stuff after…


    Again – replace “WebApplication1” with your project name.

    Note that the iisexpress.exe we point at MUST be the 64-bit version, or we won’t be able to debug later on. The 64-bit version is located in c:\program files\ directory, and the 32-bit version in – you guessed it – the c:\program files(x86)\ directory.

    To get IIS Express going from VS Code, press CTRL+SHIFT+P, to bring up the command prompt, then type/select “Tasks: Run Task” and select “iisexpress”.

    You should see something like this in the VS Code terminal window (you may have to bring it up):

    Starting IIS Express ...
    Successfully registered URL "
    http://localhost:5006/" for site "Development Web Site" application "/"
    Registration completed
    IIS Express is running.
    Enter 'Q' to stop IIS Express


    You can now open a browser and point at http://localhost:5006, your web application should hopefully start.

    Debugging

    Debugging in VS Code is defined in the launch.json file. VS Code has to “attach” to the iisexpress.exe process. So create a launch.json file in .vscode directory, and add this:

    launch.json

    {

        "version": "0.2.0",

        "configurations": [

          {

            "name": ".NET Attach",

            "type": "clr",

            "request": "attach",

            "processName": "iisexpress.exe",

          }

        ]

      }

     


    To “attach” and debug our running application. Press F5 in VS Code. If all is well, the debugger should start running, and you should be able to set breakpoints and whatnot. I’ve not looked at how to debug *.cshtml files yet, but I’m sure it can be done if needed.

    Build, Run and Browse

    It’s possible to do build, run in iis express and start Chrome/Edge in one step for convenience. This is my full tasks.json file for that. On F5 it will run the default task “build run browse” which depends on the tasks “build”, “iisexpress” and “browser”. You might want to exclude the “browser” subtask, but here it is:

    {

        // See https://go.microsoft.com/fwlink/?LinkId=733558

        // for the documentation about the tasks.json format

        //https://bigfont.ca/debug-an-iis-express-web-application-from-vs-code/

        //appcmd add site /name:"WebApplication1" /bindings:https/*5006:localhost /physicalPath:C:\code-test\framework\WebApplication1\WebApplication1\obj\Debug\Package\PackageTmp

        //"C:\Program Files (x86)\IIS Express\appcmd.exe" add site /name:"WebApplication1" /bindings:https/*5006:localhost /physicalPath:C:\code-test\framework\WebApplication1\WebApplication1\obj\Debug\Package\PackageTmp

        "version": "2.0.0",

        "tasks": [

            {

                "label": "build run browse",

                "dependsOn": [

                   "build",

                   "iisexpress",

                   "browser"

                ],

                "group": {

                   "kind": "build",

                   "isDefault": true

                }

            },

            {

                "label": "build",

                "type": "shell",

                "command": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\MSBuild\\Current\\Bin\\msbuild.exe",

                "args": [

                   "${workspaceFolder}/WebApplication1/WebApplication1.csproj",

                   "/t:build",

                   "/p:GenerateFullPaths=true",

                   "/p:Configuration=Debug",

                   "/consoleloggerparameters:NoSummary"

                ],

                "group": "build",

                "presentation": {

                   "reveal": "silent"

                },

                "problemMatcher": "$msCompile"

            },

            {

                "label": "iisexpress",

                "type": "shell",

                "command": "C:\\Program Files\\IIS Express\\iisexpress.exe",

                "args": [

                   "/path:${workspaceRoot}\\WebApplication1",

                   "/port:5006"

                ],

                "presentation": {

                   "reveal": "silent"

                },

                "problemMatcher": "$msCompile"

            },

            {

                "label": "browser",

                "type": "shell",

                "command": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",

                "args": [

                   "http://localhost:5006"

               ],

               "problemMatcher": []

           }

       ]

    }

     

     

     

    Hopefully this might help some of you out there to use VS Code with Framework projects and transition over to .net 5 or 6. VS Code is still fast and really, really useful, though VS 2022 looks awesome and seems to outshine VS Code for me.

  • WebView2 Getting Started

    The Microsoft WebView2 control allows you to embed Web Tech in native applications. It’s miles better than the old web browser controls. The WebView2 control is based on the Chromium platform.

    The official docs for the control are found here: https://docs.microsoft.com/en-us/microsoft-edge/webview2/

    Pre-reqs

    Important note (as of 2021-01-20) - ensure you installed the following list of pre-requisites before proceeding:

    I suggest you visit https://www.microsoftedgeinsider.com/download and get the “Edge Canary Channel” that way.

    Install WebView2 SDK in Visual Studio

    Once you’ve created your WebForms or WPF project, install the Microsoft.Web.WebView2 package from Nuget:

    PM> Install-Package Microsoft.Web.WebView2

    Initializing WebView2 Control

    Much about the control is asynchronous, and to make sure the control is loaded and ready, add an InitializeAsync() method to your form constructor, and place the events of interest there, like so:

            public webView2TestForm()
            {
                InitializeComponent();
                InitializeAsync();
            }
    
            async void InitializeAsync()
            {
                webViewControl.NavigationCompleted += WebViewControlOnNavigationCompleted;
                webViewControl.WebMessageReceived += WebViewControlOnWebMessageReceived;
    
                await webViewControl.EnsureCoreWebView2Async(null);
            }
    
    

    Send Message to Web Page

    Easiest way to communicate between the web page and the native application is to send messages. From the native app:

    webViewControl.CoreWebView2.PostWebMessageAsString("proxy.object.added");
    

    To handle messages, the web page need some scripting:

            window.chrome.webview.addEventListener('message',
                event => {
                    console.log('Got message from host!');
                    console.log(event.data);
                    handleMessages(event.data);
                });
    
    

    Send Message to Host

    To send a message from the web page

    window.chrome.webview.postMessage('page.ready');
    

    To handle messages from web page in the host:

            private void WebViewControlOnWebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
            {
                var message = e.TryGetWebMessageAsString();
                switch (message)
                {
                    case "page.ready":
                        Trace.TraceInformation("Got page.ready message!");
                        break;
                    default:
                        Trace.TraceWarning("Unknown message received: " + message);
                        break;
                }
            }
    
    

    Proxy Objects

    One of the coolest features availeble is to send a “proxy object” from the native application to the web page. There are some limitations but powerful enough. The best info I’ve found is this: https://docs.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2.addhostobjecttoscript 

    The class/object must be exposed as a COM object (!):

        [ClassInterface(ClassInterfaceType.AutoDual)]
        [ComVisible(true)]
        public class ProxyHostObject
        {
            // sample property
            public string Name { get; set; } = "Johan";
    
            // sample method
            public string GetName()
            {
                return Name;
            }
    
            // sample indexed property
            [System.Runtime.CompilerServices.IndexerName("Items")]
            public string this[int index]
            {
                get => _dictionary[index];
                set => _dictionary[index] = value;
            }
            private Dictionary<int, string> _dictionary = new Dictionary<int, string>();
        }
    
    

    The use of the ClassInterface attribute is discussed in the Edge github repo, because the AutoDual value is not recommended in the docs, and even deprecated in dotnet:

    Using AutoDual is strongly discouraged because of the versioning limitations described in System.Runtime.InteropServices.ClassInterfaceAttribute.

    The issue is discussed here: https://github.com/MicrosoftEdge/WebView2Feedback/issues/517

    To create and use the proxy object in the web page:

        async function handleMessages(message) {
            switch (event.data) {
            case 'proxy.object.added':
                {
                    const obj = window.chrome.webview.hostObjects.proxyobject;
                    console.log(obj);
    
                    var name1 = await obj.Name;
                    console.log('name prop: ' + name1);
                    var name2 = await obj.GetName();
                    console.log('name func: ' + name2);
    
                    obj.GetName().then(name => {
                        console.log("GetName promise name: " + name);
                    });
    
                    // Indexed properties
                    let index = 123;
                    obj[index] = "test";
                    let result = await obj[index];
                    console.log(result);
                }
                break;
    
            default:
                console.log("unknown message: " + event.data);
            }
        }
    
    
  • Subsequent calls to AcquireToken()

    Using the Active Directory Authentication Library (ADAL) and getting that annoying flash from the authentication dialog on subsequent calls? Maybe you’re creating a new AuthenticationContext every time? In that case the call to AcquireToke() by the context cannot keep and lookup the cached token and refreshtokens. You should try to keep a cached or static version of the AuthenticationContext alive between calls. Something like this of you’re calling a web api or similar:

    private static readonly AuthenticationContext AuthenticationContext = new AuthenticationContext("https://login.windows.net/domain.com");

    private static AuthenticationResult GetAuthenticationToken()
    {
    var acquireToken = AuthenticationContext.AcquireToken("https://domain.com/WebApp-something.azurewebsites.net", //resource id of the web api
    "acca2f90-5f76-45b5-8ec3------", //the client id
    new Uri("https://domain.com/YourClientRedirectUrl")); //client redirect url

    return acquireToken;
    }

    public static async Task<string> GetRequestAsync(string requestUri)
    {
    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
    var authorizationHeader = GetAuthenticationToken().CreateAuthorizationHeader();
    request.Headers.TryAddWithoutValidation("Authorization", authorizationHeader);
    var response = await client.SendAsync(request);
    var responseString = await response.Content.ReadAsStringAsync();
    Debug.WriteLine(responseString);
    return responseString;
    }

  • Secure ASP.NET Web API with Windows Azure AD

    Note that the APIs, tools and methods change quickly in this area, this blog post will get old and die eventually…

    Many organizations now look at the Azure environment to host their websites and web APIs, and some decide to move their mail and Active Directory too. Now with the latest updates and previews in Azure, you’re able to secure your web APIs with Azure AD. Vittorio Bertocci wrote an article for MSDN Magazine about Secure ASP.NET Web API with Windows Azure AD and Microsoft OWIN Components and it worked fine up until a couple of weeks ago when things moved around in these parts of Azure Smile

    I will try to describe in detail how to secure your web API with Azure Active Directory now, using Visual Studio 2013 and the preview of ADAL (Active Directory Authentication Library) package.

    Create a web API project

    Fire up Visual Studio and create a new ASP.NET Web Application. I’m calling mine “johandanforth”, I’m selecting “Web API” and click the “Change Authentication”

    image

    In the next dialog, click “Organizational Account” and enter the domain of your Azure AD tenant, in my case it’s “irm.se”:

    image

    After you press “OK” you’ll be asked to login with your Azure AD account, then “OK” again and Visual Studio will create a web application resource in your Azure AD. Now look it up in the Azure Management application. Note that you may have to log out and in again or restart the Azure management web app to see the newly created application.

    In my case the application has been named “johandanforth” and is for securing your development project on localhost. The SIGN-ON URL (also called the APP URL in the management application) is https://localhost:44310/ which can be seen both on the applications overview and if you click on the application and go to the CONFIGURE “tab”:

    image

    The sign-on url should be the same as where the web API is hosted, in this case the same localhost-settings as you got in the development project web-settings.

    Open up web.config of your web API project and have a look at these settings:

        <add key="ida:Audience" value="https://irm.se/johandanforth" />
        <add key="ida:ClientID" value="d169beb7-34bc-441b-8b93-87e3181a1132" />

    The “ida:Audience” in web.config correspond to the value of APP ID URI of the application resource in the management portal and the “ida:ClientID” correspond to the CLIENT ID in the portal.

    image

    Update the web application manifest

    Before you any application can access this resource, we must update the “manifest”. Still on the CONFIGURE tab for your web API resource, there should be a MANAGE MANIFEST menu option down at the bottom toolbar. Click it and select “Download Manifest”. It’s a json-text-file, and should save it somewhere where you know is, because we will add a section to it and then upload it again using the same menu option:

    image

    Open the json-manifest and replace the "appPermissions": [], section with this:

    "appPermissions":[
    {
    "claimValue":"user_impersonation",
    "description":"Allow the application full access to the service on behalf of the signed-in user",
    "directAccessGrantTypes":[

    ],
    "displayName":"Have full access to the service",
    "impersonationAccessGrantTypes":[
    {
    "impersonated":"User",
    "impersonator":"Application"
    }
    ],
    "isDisabled":false,
    "origin":"Application",
    "permissionId":"b69ee3c9-c40d-4f2a-ac80-961cd1534e40",
    "resourceScopeType":"Personal",
    "userConsentDescription":"Allow the application full access to the service on your behalf",
    "userConsentDisplayName":"Have full access to the service"
    }
    ],
     
    At the moment, there doesn’t seem to much in way of documentation on this manifest file, but it should work without modifications. I’ll try to write something about this manifest file as soon as I get some more docs on it.
     
    Next thing you do is upload the modified manifest file. Note that the portal may give you an error message during upload, but things seems to work anyway! It may look like this:
    image

    Create a client

    Now let’s try and access the sample ValuesController Web API in your development environment using a web browser, Fiddler or similar. In my case it’s https://localhost:44309/api/values and you should get a HTTP/1.1 401 Unauthorized error back. To be able to access the protected resource, you must add a client resource in the AD and configure it to access the web API.

    If you are not there already, in the Azure management portal, go to Active Directory, click on your domain name and select the APPLICATIONS tab. Then click the ADD-icon down the center of the bottom toolbar. Then go ahead and select “Add an application my organization is developing”:

    image

    Enter a name for your client (I’m going with “johandanforth-client”, and make sure you select NATIVE CLIENT APPLICATION because we’re going to write a simple Windows WPF client to call our web API:

    image

    On the second page, type in a redirect url for your client – it can be anything as long as it is a valid url. I’m going with https://irm.se/johandanforth-client.

    image

    Your client is now created, but the last step to do is to give permission to our web API. Scroll down to the bottom of the client application CONFIGURE page and look at the “permissions to other applications (preview)” section. In the dropdown marked “select application” you should be able to see and select your web API. You must also select the “Delegated permissions” dropdown and mark the only option available for you. As you can see, the description matches the text in the manifest file:

    image

    Remember to SAVE!

    Almost there, hang on…

    Create a Windows WPF application for testing

    Add a new Windows WPF Application to your solution, I’m calling it “johandanforth.client”, and create a button with a click-event or something to hold the code that will authenticate and get values from your API. Bring up NuGet and search for “ADAL”, make sure you have “Include Prerelease” selected:

    image

    Install the prerelease package from February 2014 (it will probably be updated soon), then paste this code into the click-event of that button you created earlier:

    using System;
    using System.Net.Http;
    using System.Windows;
    using Microsoft.IdentityModel.Clients.ActiveDirectory;

    namespace johandanforth.client
    {
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
    InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
    //this is to accept dev certificates - do not use in production!
    System.Net.ServicePointManager.ServerCertificateValidationCallback = ((a, b, c, d) => true);

    var ac = new AuthenticationContext("https://login.windows.net/irm.se"); //ad domain = irm.se

    var ar1 = ac.AcquireToken("https://irm.se/johandanforth", //app id uri of the web api
    "91b4bc31-92c2-4699-86f5-fa84a718da30", //the client id
    new Uri("https://irm.se/johandanforth-client")); //the client redirect uri

    var authHeader = ar1.CreateAuthorizationHeader();

    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44310/api/values");
    request.Headers.TryAddWithoutValidation("Authorization", authHeader);
    var response = await client.SendAsync(request);
    var responseString = await response.Content.ReadAsStringAsync();
    MessageBox.Show(responseString);
    }
    }
    }

    There are a few lines that must be change to work with your sample code. First change the AuthenticaitonContext to match your Azure AD domain/tenant name:

    var ac = new AuthenticationContext("https://login.windows.net/irm.se");
    

    Next look at the code part which acquires a token – this is when the login dialog pops up and asks the user to log in using his or hers organizational account. This line corresponds to the web API uri, which is the same as the “ida:Audience” in your web.config file, so update it to match that value:

    var ar1 = ac.AcquireToken("https://irm.se/johandanforth",  

    The next line is the client id of the application client you created in Azure AD, look it up and change the id accordingly:

    "91b4bc31-92c2-4699-86f5-fa84a718da30",

    The last line is the redirect-uri of the client, look it up on the same page in the Azure management portal:

    new Uri("https://irm.se/johandanforth-client"));

                  

    You must also modify the line with the call to the web API method to match your web server localhost settings:

    var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44310/api/values");

    Now, start the web API program in debug mode and wait until you see the Home Page, then right click and start debug of the WPF client. Click the button and you should be prompted to log in with your organizational account (this is the look of it in Swedish):

    image

    After a successful login, the code continues and you should be greeted with this:

    image

    Still with me?

    Deploy to Azure

    This is all well and good (hopefully), but we want to deploy our web API to Azure and run our clients against it in the cloud. To do that we need to:

    1) Create a web site to host our web API in Azure

    2) Publish our code to the site

    3) Create an Azure AD resource for the web API (VS does this for you)

    4) Modify the manifest for the web API (like before)

    5) Give the client permission to the new resource (like before)

    6) Update web.config and the client code to match the IDs and URIs of the new resources (ida:Audience == APP ID URI == the resource you want to access)

    7) Publish the code again (to get the updated web.config uploaded)

    8) Run!

    Here’s some quick shots of some of the steps. First create a web site in Azure by selecting “WEB SITES” in the left hand menu of the Azure Portal, press the big plus-sign down in the corner and create a custom web site. I’m calling mine “johandanforth” (ignore the error message Winking smile )

    image

    Now go back to Visual Studio, right click the web API project and select “Publish…”.

    image

    Press the “Import…” button to download and import the publishing profile of the web site you created, and select the newly created Web Site in the dropdown. Click OK.

    image

    You have to authenticate one or two times to get past these steps, but should finally get to the last step of the Publish process:

    image

    When Visual Studio is done publishing, a browser page will open up with the Home Page showing:

    image

    Visual Studio should now have created a new application resource in the Azure Active Directory, so get back to the portal and have a look at the list of AD applications. A resource named “WebApp-xxxxxxxxx.azurewebsites.net” should be listed there. Note – you may have to sign out and sign in to the portal to show the web api resource. This has happened to me a couple of times!

    image

    Click on the resource and look at the details in the CONFIGURE tab.

    image

    Copy the name of the “APP ID URI” and past it into the “ida:Audience” value in the web.config file of your web API project in Visual Studio:

        <add key="ida:Audience" value="https://irm.se/WebApp-johandanforth.azurewebsites.net" />

    The same value must also be updated in the WPF client:

    var ar1 = ac.AcquireToken(https://irm.se/WebApp-johandanforth.azurewebsites.net,  

    You must also (of course) update the call to the web API method to point at the web site in the cloud:

    var request = new HttpRequestMessage(HttpMethod.Get, "https://johandanforth.azurewebsites.net/api/values");

    We’re not done yet though… now you have to do the same steps you did for the localhost resource earlier - download and update the manifest file for the web API resource and give the client resource permission to use the service.

    Finally (yes finally) – publish the web API project again to get the updated web.config file to the cloud site!

    Once the code is published, you should be able to run the client successfully.

    Please give feedback if you have problems with any step/s of this walkthrough. Other questions, bugs and such is better asked on the Windows Azure Active Directory forum. I’m still learning these things and trying to keep up with the changes Smile

  • Trust Certificates

    Just as a reminder to myself – when developing (this code should be removed in production) you may work with dev certs and get errors like "Could not establish a trust relationship for the SSL/TLS secure channel". This code snippet helps:

    System.Net.ServicePointManager.ServerCertificateValidationCallback =
    ((sender, certificate, chain, sslPolicyErrors) => true);

  • More MiniBuss Updates

    minibuss_small_thumb1_thumb MiniBuss is a micro service bus framework over msmq which consists of less than 400 lines of code, sitting inside one single source file. The project is hosted over at http://minibuss.codeplex.com

    Thanks to @CodingInsomnia for testing out the MiniBuss stuff a bit more than I did Winking smile For the samples, and for my initial testing code, I used a shared assembly with messages (events and commands), which shouldn’t be necessary. So I made a few simple changes and now you can choose to either share messages in an assembly between your sender/receiver and publisher/subscribers OR you can declare local message classes as long as those classes use the same class name and properties it should work.

    The NuGet package has been updated, and the new code is in package version 1.0.2.0.

  • A One File .NET Micro Service Bus for MSMQ?

    This last year our company has invested quite some time in looking at CQRS, which led to looking at great looking service-buses like nServiceBus, Rhino Service Bus and Mass Transit, which led me to do some bus-coding on my own, mostly for fun and for learning MSMQ.

    Inspired by the service buses mentioned above, the result became a bare-bones-one-file “micro service bus” that I call MiniBuss which sits on top of MSMQ. The file itself is only some 400 lines of code and supports send, receive, reply, publish and subscribe/unsubscribe.

    Setting up a sender may look something like this:

    var bus = new MiniBuss.ServiceBus();

    bus.RegisterMessageEndpoint<HelloCommand>("minibuss_receiver1@johan-dell-ssd");

    bus.Start();

    bus.Send(new HelloCommand { Guid = Guid.NewGuid(), Message = "Hello" });

    Create the bus, register a message and tell it where messages of this type should go, start the bus and send the message.

    Setting up a receiver may look something like this:

    var bus = new ServiceBus { LocalEndpoint = "minibuss_receiver1" };

    bus.RegisterMessageHandler<HelloCommand>(command => Console.WriteLine(command.Message + " Guid: " + command.Guid));

    bus.Start();

    Create the bus and tell it which endpoint to listen to (which creates a local MSMQ queue if necessary) and tell it which message type to listen for and which delegate to kick off when such a message is received.

    Similarly, when doing a receive/reply, you would have to create the bus on the sender side with a local endpoint and register a message-handler for replies, like this:

    var bus = new MiniBuss.ServiceBus { LocalEndpoint = "minibuss_sender1" };

    bus.RegisterMessageEndpoint<HelloCommand>("minibuss_receiver1@johan-dell-ssd");

    bus.RegisterMessageHandler<HelloResponse>(reply => Console.WriteLine("Reply from receiver: " + reply.Message));

    bus.Start();

    Console.WriteLine("Sending command...");
    bus.Send(new HelloCommand { Guid = Guid.NewGuid(), Message = "Hello" });

    The receiver would do a bus.reply() like this:

    var bus = new ServiceBus { LocalEndpoint = "minibuss_receiver1" };

    bus.RegisterMessageHandler<HelloCommand>(command =>
    {
        Console.WriteLine(command.Message + " Guid: " + command.Guid);

        bus.Reply(new HelloResponse { Guid = Guid.NewGuid(), Message = "Hello back!" });
    });

    bus.Start();

    The MiniBus also supports publish to multiple subscribers. A simple publisher would create a bus with a local endpoint (to receive subscribe/unsubscribe commands), tell it to handle subscriptions for a certain event, then start publishing something every 5 seconds (as an example):

    var bus = new MiniBuss.ServiceBus { LocalEndpoint = "minibuss_publisher1" };

    bus.HandleSubscriptionsFor<SomethingHappenedEvent>();

    bus.Start();    

    Task.Factory.StartNew(() => PublishingThread(bus), TaskCreationOptions.LongRunning);

    Console.WriteLine("Done, press ENTER to exit");
    Console.ReadLine();
    private static void PublishingThread(MiniBuss.ServiceBus bus)
    {
        while (true)
        {
            Thread.Sleep(5000);
            var guid = Guid.NewGuid();
            Console.WriteLine("Publishing event with guid " + guid);
            bus.Publish(new SomethingHappenedEvent() { Guid = guid, Sent = DateTime.Now });
        }
    }

    Any clients interesting in subscribing to events from the publisher would create a bus with a local endpoint, start the bus and then send a subscribe command to the publisher, telling it you’re interested in subscribing to a certain type of event and which delegate to handle it:

    var bus = new MiniBuss.ServiceBus {LocalEndpoint = "minibuss_subscriber1"};

    bus.Start();

    bus.Subscribe<SomethingHappenedEvent>("minibuss_publisher1@localhost",
        @event => Console.WriteLine("something happened at {0}, event id {1}",
            @event.Sent, @event.Guid));

    Console.WriteLine("Waiting for events, press ENTER to exit");
    Console.ReadLine();

    bus.UnSubscribe<SomethingHappenedEvent>("minibuss_publisher1");

    Now, the question is, what do you think? I know there are issues with the code, like how to make message-handlers multi-threaded/concurrent without messing things up (it’s single threaded right now), and how to best handle exceptions, rollbacks and re-tries . Right now handling exceptions in send and receive works pretty well within a TransactionScope() together with ADO.NET, and if there’s an exception, the message is moved the an error-queue. No re-try or anything, only rollback and move to xxx_error. Also, the publisher doesn’t persist subscriptions, so if it is restarted subscribers wouldn’t know. You know, things like that.

    I’m a user of the micro-orm called Dapper and like it a lot, so I’m thinking that maybe I should release this micro-bus as open source and see where people may take it, if anywhere? Maybe just down the drain because they figure out this service bus is dangerous to use and risk loosing messages or something (which would be extremely good to know :)

    Or maybe this code is useless because you already got nServiceBus and Rhino out there and coders don’t need another service bus?

    What do you say?

  • New Stuff, New Stuff, Go Download Already

    First of all you got the VS 2005 Service Pack 1 for Team Suite, and it's said to contain some 2200 fixes?!?! It's available for download here. Note that it's a 430 MB download and it's also said to take some time to install.

    Second good thing, and also a must to download and check out, is the RC1 of ASP.NET AJAX. You can read about it on Scott's blog. As usual, Scott gives you the info you need. I'm pretty sure that this package will used ALOT in the next couple of years, until something else pops up or becomes "cooler". Perhaps WPF(e) will beat it eventually, Another thing - the ASP.NET hompage news also says:

    The Microsoft AJAX Library is also available in an easy-to-install, standalone package for development on non-Windows systems. 

    Sounds interesting, don't you think? You can download and read more about ASP.NET AJAX on their webby,

  • How to Use Msbuild.exe with CruiseControl.NET

    I just updated my primer/tutorial/walkthrough on CruiseControl.NET with some information about how to use msbuild.exe instead of devenv.exe in your minimal cc.net configuration. One good reason to go with msbuild is that you don't need to install VS.NET on a dedicated build server, and you can also target unit tests, performance tests, code analysis etc. that you may have added using the Team Edition versions of VS.NET.

    Please check it out and comment on it if you please.

  • [Podcasts] .NET Podcasts

    I've soon listened to all shows that have been recorded by Scott Hanselman and Carl Franklin on Hanselminutes (http://www.hanselminutes.com/), and I've started to dig around for some more podcasts, preferably similar to the Hanselminutes stuff. I've been listening to .NET Rocks (http://www.dotnetrocks.com/) for some time as well, and I just ran upon the Polymorphic Podcast (http://polymorphicpodcast.com/) which seems to be just great. Polymorphic is about most things .NET related and it's hosted by Craig Shoemaker.

    Then there's the ASP.NET Podcasts, hosted by Wallace B. (Wally) McClure and Paul Glavich, which I haven't listened to (or looked at for that matter because they also have some viewable material) at http://aspnetpodcast.com or better yet http://aspnetpodcast.com/CS11/blogs/asp.net_podcast/default.aspx

    If you know of any other similar podcasts, please let me know and I'll add them to this page.

    I need to think of a way to automatically download the files and have them synced with my SonyE ricsson mobile phone... Or get a better "download deal" with my phone company and create a small program that I can run on the mobile phone to download these podcasts directly. It's too expensive for me to download these files over the mobile network as I have to pay for the bytes...