Asp.Net Core - James Montemagno https://staging.montemagno.com/tag/asp-net-core/ https://staging.montemagno.com/content/images/2017/08/MonogramIcon_Orange_NoBuffer.png Asp.Net Core - James Montemagno https://staging.montemagno.com/tag/asp-net-core/ Hugo -- gohugo.io Tue, 13 Oct 2026 22:20:07 GMT 60 Developing & Working with .NET Containers on Windows ARM Devices https://staging.montemagno.com/developing-working-with-net-containers-on-windows-arm-machines/ 65a9f8471270dd000126e7cb Fri, 19 Jan 2024 18:46:22 GMT

I am by no means a cloud-native developer, I am a client developer. I have spent some time though to get a general understanding about microservices, images, containers, docker, and all the buzz words that surround the topic. I recently got really into DevContainers and using them on GitHub Codespaces and Visual Studio Code to create an environment to run apps in. From there, I went down a rabbit hole of educating myself more by taking Microsoft Learn training courses, watching the new containers for beginner series, and actually trying to build something myself.

However, this is where I always seem to get into trouble as my main work machine every day where I am doing training is a Windows ARM device. I have been using the Project Volterra device for a long time and I simply love it. The ecosystem of what I can develop and my day to day is ALMOST identical to my normal x86 machine. One area as of time of writing this that always gets me is Docker and the lack of support Docker Desktop on Windows ARM (although it is coming in the future). DevContainers... needs Docker.... container development...needs Docker.... and there we have the issue.... or do we...

Enter WSL

Yes, the Window Subsystem for Linux to the rescue! We are creating Linux containers anyways so might as well run them in WSL! Just like the Windows Subsystem for Android enables me to develop Android apps easily, WSL does the same for container and dev containers. DevContainers was a simple solution, simply install Docker inside of Ubuntu on WSL and BOOM you are good to go. So elegant, so simple.

However, creating a container image with the dotnet publish -t:PublishContainer command is not so easy. In an ideal world I would just run this on my Windows machine for my .NET app, it would create the image, and then I could view it in Docker Desktop. Well.... no docker desktop. So, I could use WSL to run the command INSIDE of Ubuntu and then use Docker inside of WSL to run it! WHOA! That would work... if there was a distribution of Ubuntu out of the box that supported installing .NET 8 SDK for Ubuntu ARM easily. You technically need Ubuntu 23.10 to do this, and easy install of Ubuntu is only at 22.04. Now YES you can totally install any distro of Linux into WSL... but I like the "easy" button. Additionally, since I still don't have any Docker Desktop in this scenario, I would still have to use the Docker command line for management.

Enter Podman & Podman Desktop

But what if I told you don't need to have Docker to run images and containers. They are standard and other things can run them do such as Podman which is available on Windows, works by using WSL under the hood, and works on ARM devices!!!Oh, it also is super easy to install with just a normal installer!

After you have it installed, all you need to do is run podman machine init and start it up with podman machine start.

Now, since I love GUIs, it is time to install Podman Desktop that will easily help you boot podman, view images, create and run containers, and pretty much anything else you would want to do. It will also walk you through the complete set-up and installation process as well if you haven't done that yet or need to make changes in the future.

Podman Desktop home page

Let's create a .NET container!

Now, the fun part here is that I can use all my normal Windows tools including the .NET CLI, VS Code, or Visual Studio to create my images with the .NET SDK and run them in podman. Podman just sits in the background and handles the logistics. I don't have to worry about signing into WSL or anything.

Now, we can create a new .NET web app with dotnet new web -o HelloPodman.

Then it is time to publish it with dotnet publish -t:PublishContainer.

This should give you some output like this:

HelloPodman -> C:\Users\jamont\Desktop\HelloPodman\bin\Release\net8.0\HelloPodman.dll
  HelloPodman -> C:\Users\jamont\Desktop\HelloPodman\bin\Release\net8.0\publish\
  Building image 'hellopodman' with tags 'latest' on top of base image 'mcr.microsoft.com/dotnet/runtime:8.0'.
  Pushed image 'hellopodman:latest' to local registry via 'podman'.

Now, let's run it! I could run it manually with podman commands in my normal Windows Terminal with any shell including normal cmd. Or I could open up Podman Desktop and create a new container from the image.

When you hit the play icon it will take you to the configuration screen where it will be pre-configured with the dotnet entry point and 8080 for port:

Create the container and then you can launch it!

There you have it! Your Windows ARM machine is configured and ready to roll to develop containers and microservices with .NET!

]]>
Add ASP.NET Core's Dependency Injection into Xamarin Apps with HostBuilder https://staging.montemagno.com/add-asp-net-cores-dependency-injection-into-xamarin-apps-with-hostbuilder/ 5cc7df16b2f3d500bff4c9d0 Tue, 18 Jun 2019 21:53:00 GMT

Dependency injection(DI) and inversion of control (IoC), have been a recurring theme in questions that I have received over the last six years. Sometimes it is around using constructor injection(), simple service containers, and often around full frameworks such as Prism or MVVM Light. I will be honest with you, I have never been a fan of DI/IoC when building mobile apps. My main reason is that there has never been any official pattern or recommendations from Google or Apple (or Microsoft/Xamarin) when building Android and iOS apps. Also, I have always been worried around startup performance in my apps and didn't want to introduce another dependency. However, it is 2019 and I think that my concerns have finally been resolved after talking with my friend Glenn Condron, and here is why:

  1. There is a new official library from Microsoft that handles everything for you.
  2. Using this model gives you other powerful features like logging, HTTPClientFactory, and more.
  3. These devices are crazy powerful and the frameworks we use such as Xamarin.Forms, have really matured.

So, what is this magical library? It is the Microsoft.Extensions framework, but specifically the Generic Host framework that lives inside of Microsoft.Extensions.Hosting. It is a platform independent implementation of ASP.NET Core's extensibility framework.

Microsoft.Extenions

The cool part about this library is that if you already have been building ASP.NET Core applications, then you already know exactly how to use the library. Additionally, it means that just about every other library that extends it works with your Xamarin apps like app configuration, logging, HTTPClientFactory, Polly, and more! Let's start with the basics and first setup a HostBuild, which is the base for the Extensions library and then setup some dependency injection with constructor injection.

Installation and Setup

The first thing to do is to install the v3 pre-release Micosoft.Extensions.Hosting NuGet into all of our projects. This will give our projects access to the base foundation and also includes the ability to use the built-in logging framework and application configuration via a json file.

With the library installed we will create two files in our shared code (also if you are building a single iOS/Android app this will also work):

Startup.cs

Will host all of our HostBuilder configuration and setup all of the dependencies in our application. Here is the base foundation for the file with all of the using statements we will need:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Xamarin.Essentials;

namespace MyApp
{
    public static class Startup
    {
        public static IServiceProvider ServiceProvider { get; set; }
        public static void Init()
        {

        }

        static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
        {

        }
    }
}

appsettings.json

This file will need to be set as an EmbeddedResource and will host configuration properties and settings. Here is a generic default appsettings file:

{
  "Hello": "World",
  "Environment": "Development",
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Host Builder setup

The extensions library has a few main concepts to understand:

  1. HostBuilder: Acts as a builder for adding services (logging, app config, etc.) onto the app.
  2. IServiceProvider: Handles all dependency injection & acts as a service locator and comes from the HostBuilder.

Our Init method must be called from either the main Xamarin.Forms or platform specific app startup. We will fill in the Init method by getting a stream to the app settings file so the HostBuilder can read it, configure services, and setup the built in logging service:

var a = Assembly.GetExecutingAssembly();
using var stream = a.GetManifestResourceStream("MyAssemblyName.appsettings.json");

var host = new HostBuilder()
            .ConfigureHostConfiguration(c =>
            {
                // Tell the host configuration where to file the file (this is required for Xamarin apps)
                c.AddCommandLine(new string[] { $"ContentRoot={FileSystem.AppDataDirectory}" });

                //read in the configuration file!
                c.AddJsonStream(stream);
            })
            .ConfigureServices((c, x) =>
            {
                // Configure our local services and access the host configuration
                ConfigureServices(c, x);
            })
            .ConfigureLogging(l => l.AddConsole(o =>
            {
                //setup a console logger and disable colors since they don't have any colors in VS
                o.DisableColors = true;
            }))
            .Build();

//Save our service provider so we can use it later.
ServiceProvider = host.Services;

Configure Dependencies

We have setup our HostBuilder and called ConfigureServices, but we haven't done anything yet. So let's do it!

Let's say we have the following code for a ViewModel and a service that it needs to use:

public interface IDataService
{
    void DoStuff();
}

public class MyDataService : IDataService
{
    // We need access to the ILogger from Microsoft.Extensions so pass it into the constructor
    ILogger<MyDataService> logger;
    public MyDataService(ILogger<MyDataService> logger)
    {
        this.logger = logger;
    }

    public void DoStuff()
    {
        logger.LogCritical("You just called DoStuff from MyDataService");
    }
}

public class MockDataService : IDataService
{
    // We need access to the ILogger from Microsoft.Extensions so pass it into the constructor
    ILogger<MyDataService> logger;
    public MockDataService(ILogger<MyDataService> logger)
    {
        this.logger = logger;
    }

    public void DoStuff()
    {
        logger.LogCritical("You just called DoStuff from MockDataService");
    }
}

public class MyViewModel
{
    IDataService dataService;
    public MyViewModel(IDataService dataService)
    {
        this.dataService = dataService;
    }

    public void DoIt()
    {
        dataService.DoStuff();
    }
}

Here we have a ViewModel that needs access to the IDataService and one of the implementations needs access to a ILogger. This is where the ServiceCollection comes in allowing us to configure all of our dependencies. Let's setup the ConfigureServices method in the Startup.cs again and configure these new classes.

static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
{
    // The HostingEnvironment comes from the appsetting.json and could be optionally used to configure the mock service
    if (ctx.HostingEnvironment.IsDevelopment())
    {
        // add as a singleton so only one ever will be created.
        services.AddSingleton<IDataService, MockDataService>();
    }
    else
    {
        services.AddSingleton<IDataService, MyDataService>();
    }

    // add the ViewModel, but as a Transient, which means it will create a new one each time.
    services.AddTransient<MyViewModel>();

    //Another thing we can do is access variables from that json file
     var world = ctx.Configuration["Hello"];
}

HostingEnvironment

Access Dependencies

With our HostBuilder and dependencies configured, we can now access them from anywhere. Since we only went up to the ViewModel level we will need to grab it from the ServiceProvider in the code behind from our page:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = Startup.ServiceProvider.GetService<MyViewModel>();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        ((MyViewModel)BindingContect).DoIt();
    }
}

When we call GetService the Microsoft.Extensions framework will handle creating and injecting any dependencies including our IDataService and the ILogger that came for free just by using the library. When we call DoIt in the OnAppering our app ill print out a message to the console using the logger that will have info of what data service it was using.

HTTPClientFactory In Your Xamarin App!

That's right, if you are using Microsoft.Extensions you can use the awesome HTTPClientFactory class that is essentially HTTPClient done right! It handles caching, retries, logging, and all other sorts of awesome! It is really easy to put into your app with just a few lines of code.

First, we will need to install the v3 prerelease Microsoft.Extensions.Http NuGet to get access to HTTPClientFactory. Then in the ConfigureServices method add the following line of code:

services.AddHttpClient();

With this single line of code in place it is now time to get access to the HTTPClientFactory from one of our classes. This is handled like our interface that was passed in as a parameter to the constructor. Microsoft.Extensions takes care of everything for you:

public class MyDataService : IDataService
{
    ILogger<MyDataService> logger;
    HttpClient client;
    public MyDataService(ILogger<MyDataService> logger, IHttpClientFactory httpClientFactory)
    {
        this.logger = logger;
        client = httpClientFactory.CreateClient();
    }

    public void DoStuff()
    {
        logger.LogCritical("You just called DoStuff from MyDataService");
    }
}

If you don't need access to the IHttpClientFactory at all this code can be simplified down to just passing in the HttpClient itself:

ILogger<MyDataService> logger;
HttpClient client;
public MyDataService(ILogger<MyDataService> logger, HttpClient client)
{
    this.logger = logger;
    this.client = client;
}

What is cool now is that when you make any calls with this HttpClient you will automatically get console logging, which is super helpful:

Response

To top it off you can even extend the HttpClient beyond just logging and introduce Polly into the mix with the Microsoft.Extenions.Http.Polly library that will enable you to automatically setup retries and other really cool features. You can find an example of this in my "First App Example" with ASP.NET Core + Xamarin

Platform Specific Dependencies

At this point you are probably like WOW, this is amazing, but what about platform specific implementations that I may need to get access to. Do not fear because it is totally possible and pretty easy to setup. Instead of calling the Init from your shared code, you can call it from your iOS/Android project and pass in a configuration Action like this:

First, let's modify the Init:

public static App Init(Action<HostBuilderContext, IServiceCollection> nativeConfigureServices)
{
    // Resource code

    var host = new HostBuilder()
                    //ConfigureHostConfiguration
                    .ConfigureServices((c, x) =>
                    {
                        //Add this line to call back into your native code
                        nativeConfigureServices(c, x);
                        ConfigureServices(c, x);
                    })
                    // Logging
                    .Build();
}

Then from inside of the Android project's MainActivity and iOS project's AppDelegate you can call this Init method:

Android Example

public class MainActivity : FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(savedInstanceState);

        //setup code

        Startup.Init(ConfigureServices);
        LoadApplication(new App());
    }

    void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
    {
        services.AddSingleton<INativeCalls, NativeCalls>();
    }
}

public class NativeCalls : INativeCalls
{
    public void OpenToast(string text)
    {
        Toast.MakeText(Application.Context, text, ToastLength.Long).Show();
    }
}

iOS Example

[Register("AppDelegate")]
public partial class AppDelegate : FormsApplicationDelegate
{
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        //Init Code:

        Startup.Init(ConfigureServices)

        LoadApplication(new App();

        return base.FinishedLaunching(app, options);
    }

    void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
    {
        services.AddSingleton<INativeCalls, NativeCalls>();
    }
}

public class NativeCalls : INativeCalls
{
    public void OpenToast(string text)
    {
        var vc = UIApplication.SharedApplication.KeyWindow.RootViewController;
        var okAlert = UIAlertController.Create(string.Empty, text, UIAlertControllerStyle.Alert);
        okAlert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
        vc.PresentViewController(okAlert, true, null);
    }
}

Inject The Entire App

As you can see this framework is extremely flexible and allows for optimal extensibility, but you can go even further. As I was trying out this API Glenn challenged me to see how far I could take this dependency/constructor injection madness... so I took it all the way up to the app level. That is right, I injected the entire app, pages, and view models.... because why not! Well maybe you shouldn't do this, but it is pretty cool.

Keeping the same dependencies and view models from above all we need to do is update our MainPage, App, and Init calls:

MainPage

public partial class MainPage : ContentPage
{
    //simply pass in the view model you desire!
    public MainPage(MyViewModel viewModel = null)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }
}

App

There are a few ways to do this. You could pass in the page that you desire into the App constructor or you could have some logic and grab it from the ServiceProvider:

public App()
{
    InitializeComponent();
    MainPage = ServiceProvider.GetService<MainPage>();
}

Update Init

This is where it gets pretty cool, we will create Transient and Singletons of all of the services, view models, pages, and the app itself and have the method return the App intead of being a void method.

public static App Init(Action<HostBuilderContext, IServiceCollection> nativeConfigureServices)
{
    //all of the same code from before
    return ServiceProvider.GetService<App>();
}

static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
{
    services.AddHttpClient();
    services.AddSingleton<IDataService, MyDataService>();
    services.AddTransient<MyViewModel>();
    services.AddTransient<MainPage>();
    services.AddSingleton<App>();
}

Then, call Init from the LoadApplication method instead of calling Init randomly in the iOS/Android project:

LoadApplication(Startup.Init(ConfigureServices));

Just like that we dependency injected our entire application and that is crazy! If you want to try it yourself, you can grab my sample project from GitHub that shows off just about everything in this blog post.

Required Versions of Xamarin/VS

As of today, you should be able to develop and debug iOS/Android apps with all these goodies using any version of Visual Studio 2019 or Visual Studio for Mac 2019. However, if you want to use ship your app and turn on the Linker you will need to have a newer version of mono, which ships with Visual Studio 2019 16.2 (preview 2) and Visual Studio for Mac 2019 8.2 (preview). If you are on Windows you can easily install VS 2019 Preview side by side the normal release.

Watch The Build Session

I had the honor of presenting how ASP.NET and Xamarin can come closer in app model with Glenn in a 20 minute theater session. It is available on the Xamarin Developers YouTube channel:

Learn More

This stuff is super fun and I really hope that it takes off and we can encorporate it into user testing, and perhaps one day into the official templates! Until then it is easy to setup and can lead to some really clean and powerful code. Be sure to read through all of the great docs for Generic Host and through any of the extensions documentation. Enjoy!

]]>
Real Time Communication for Mobile with SignalR (Core) https://staging.montemagno.com/real-time-communication-for-mobile-with-signalr/ 5bdf571ff3421000bf604cfb Mon, 12 Nov 2018 20:30:00 GMT

Real Time Communication or RTC as the cool kids call it has always been a hot topic, especially for mobile. In normal mobile development when we wanted to get updates of data we would make a web request to a server, pull down data, and update our user interface. If you wanted to get bits of data on demand and in real time you would have to integrate WebSockets or some sort of push notifications to receive data as it is happening. However, it doesn't have to be anymore with the latest version of SignalR (ASP.NET Core SignalR) which is fully compatible with .NET Standard 2.0 for ASP.NET, UWP, WPF, WinForms, and Xamarin!

download

I have been pretty obsessed with trying to learn SignalR so I started doing a weekly Twitch Stream every Saturday where I am building an app with it. You can find the latest streams on YouTube where I build the server backend and then integrate into a mobile app. In this blog I will walk you through the basics to do it all locally only on your machine.

Why SignalR (Core)

SignalR has been around for a long time and yes technically did work with Xamarin after a bunch of work. Now, with ASP.NET Core SignalR as they call it, everything has been simplified into a few simple packages for your backend server and client apps. At the center of SignalR is a "Hub" that handles incoming and outgoing messages. A client sends a message to the Hub and the Hub distributes the message to all clients that are connected:

signalr-diagram

SignalR handles all of the complex stuff for you:

  • Handles connection management automatically.
  • Sends messages to all connected clients simultaneously. For example, a chat room.
  • Sends messages to specific clients or groups of clients.
  • Scales to handle increasing traffic.
  • Supports WebSocketss, Server-Sent Events, & Long Polling and figures out which to use automatically.

Here is the introduction documentation to browse through.

Hub Backend

The code is extremely simple for the ASP.NET Core backend web application. The SignalR server library is already part of an ASP.NET Core app, so there isn't anything for the Hub besides writing a few lines of code:

using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

This code handles all messages that are sent to the "SendMessage", which when received by the Hub will send a message with the key "ReceiveMessage" to everyone connected.

Besides this Hub code we will need to configure the service and route in the Startup.cs file.

In ConfigureServices add the following code at the end of the method:

services.AddSignalR();

Then in Configure we will want to add a route for the Hub that our clients will connect to (right before UseMvc):

app.UseSignalR(routes =>
{
    routes.MapHub<ChatHub>("/chatHub");
});

A few important notes here. If you are developing on localhost you may want to disable UseHttpsRedirection until you publish to Azure. This will ensure the mobile apps can communicate on the local machine. Also if you want to integrate a web client there is a javascript/typescript library that you can use.

Client NuGet

For our mobile .NET client we simply need to install the Microsoft.AspNetCore.SignalR.Client into our iOS, Android, UWP, and .NET Standard projects and we are ready to code!

Connecting to the Hub

Everything revolves around a HubConnection, which can be found by bringing in the SignalR namespace:

using Microsoft.AspNetCore.SignalR.Client;

After that we are able to create our local instance and connect to it. We are going to connect directly to localhost since I ran it on my local machine, but you can swap out the IP if you published your backend to Azure:

HubConnection hubConnection;
public ChatViewModel()
{
    // localhost for UWP/iOS or special IP for Android
    var ip = "localhost";
    if (Device.RuntimePlatform == Device.Android)
        ip = "10.0.2.2";

    hubConnection = new HubConnectionBuilder()
        .WithUrl($"http://{ip}:5000/chatHub")
        .Build();
}

Now, all we need to do is connect to the hub. This should be done only when you need the real time connection and you should disconnect when you don't need it or when your application goes into the background:

async Task Connect()
{
    try
    {
        await hubConnection.StartAsync();
    }
    catch (Exception ex)
    {
        // Something has gone wrong
    }
}

Once connected we can start to send and receive messages.

Sending Messages

This code could not be any easier by using the InvokeAsync method on our connection:

async Task SendMessage(string user, string message)
{
    try
    {
        await hubConnection.InvokeAsync("SendMessage", user, message);
    }
    catch (Exception ex)
    {
        // send failed
    }
}

Notice here we are sending a strongly typed key to our backend, which matches the name of the method in our Hub. SignalR figures out how to invoke this method automatically.

Important note here is that there is also a SendAsync method which is what you first think that you want to use. As explained to me by Damian Edwards SendAsync is a fire and forget type of send and only ensures that the send happens from the connection and does not wait for a response at all. SendAsync is usually used by the server, whereas InvokeAsync actually ensures that the message was sent and that the server received the message.

Receiving Messages

This may be my favorite part of the API because it is really beautiful in its implemenation. You just register functions using the On method that passes in any type of arguments to a stringly typed key:

 hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
    var finalMessage = $"{user} says {message}";
    // Update the UI
});

You don't even need to be connected to register these methods, which means you have a really clean seperation of the connection and handling of the messages.

That's it! The mobile app and server are done!!! If you want a full finished sample then I have you covered as everything that I have been doing on my stream can be found on my GitHub!

signalr-in-action

Considerations for Mobile

SignalR is the first step in helping developers create awesome applications for mobile with Real Time Communciation. There are a few considerations that you should think about when implementing this type of functionality.

Connect and Disconnect

Always ensure that you connect and disconnect when appropriate. When your application goes into the background or your users leave the page that it is on.

Backgrounding

Each platform has different limitations when an app goes into the background or is fully closed by the user. You should not depend on this at all and always have a good fallback for push notifications or different polling based on the state of your app.

Handle Disconnects and Reconnects

Use Xamarin.Essentials to help out with connection state of your device and make sure to fallback gracefully when there is no internet or spotty internet.

]]>
Building an ASP.NET Core Website with Xamarin.Forms, XAML, and Ooui https://staging.montemagno.com/building-a-xaml-xamarin-forms-asp-net-website/ 5a4bd1de538da90021c4b282 Tue, 02 Jan 2018 23:39:58 GMT You read that correct, you can now totally build websites powered by XAML leveraging Xamarin.Forms and Frank Krueger's amazing Ooui library. If you haven't heard about Ooui yet, it is an amazing lightweight cross-platform UI library that brings the simplicity of native UI development to the web. For an in-depth overview take a listen to Merge Conflict Episode 72 - Xamarin.Forms on the Web:

Today, I want to show you how easy it is to get a simple website up and running using Ooui that is powered by Xamarin.Forms.

File New -> ASP.NET Core MVC

That is right you can straight up use an ASP.NET Core 2.0 web application! Ooui easily integrates and has some really nice extensions.

CoreWebApp

Add the NuGets

There are a few NuGets that we will want to add to our ASP.NET Core application:

ooui

The reason I install Xamarin.Forms manually is specifically for Visual Studio for Mac so it displays the Xamarin.Forms item templates. You would also choose the specific version of Xamarin.Formst that Ooui.Forms uses (this seems to be important, but I am not sure why), currently it is 2.4.0.38779.

Create a Xamarin.Forms Page

Ooui offers multiple ways of rendering web user interface including using standard Xamarin.Forms XAML or C#. You can use any ContentPage and several of the controls that are supported (check the GitHub page for more info).

For this example we can create a simple page with a button that we click that increases the click count:

Initialize Ooui & Xamarin.Forms

Before we can use Ooui in our app we need to initialize it in the Startup.cs file. We will need to add the following lines of code to UseOoui() and Forms.Init(); in the Configure method:

Use our XAML Page for IActionResult

When ASP.NET Core attempts to load our web application it will look at the HomeController -> Index method to return a view. By default it will load up the Razor pages that are included. We want to use the same routing, but return our Ooui Element instead. Ooui has several helper methods to convert a Xamarin.Forms ContentPage into an IActionResult.

Run the App!

At this point, we are ready to run our first Ooui/Xamarin.Forms based ASP.NET Core app!

RunApp

So Much More

Since Ooui leverages Xamarin.Forms we can leverage full data binding, converters, organize controls with layouts, and even do full navigation leveraging the ASP.NET Core routing system. Ooui adds a few nice custom controls such as LinkLabel and LinkView that act as normal href tags. In just an evening I was able to setup my full website for soundbite.fm without having to worry about html/javascript/or anything else, which was really impressive.

Learn More

It is still early days for Ooui, but I love it. You can try out all sorts of awesome Ooui samples on the Ooui homepage and of course head over to the GitHub page for more information and documentation.

You can get the source code for this sample on my GitHub.

]]>
Deploying an ASP.NET Core app to Linux on Azure App Service https://staging.montemagno.com/aspnet-core-azure-linux-app-service-deployment/ 598df8f2c121b60019bf2fd2 Tue, 28 Feb 2017 22:46:07 GMT You probably wouldn’t expect this blog post from me as I run away from building any web apps, but I have been messing around with ASP.NET Core inside of Visual Studio for Mac. I thought it would be really cool to take our default app for items and deploy it to an Azure Linux based App Service. Because… why not?!?! Also, I will make Hanselman proud.

So, first things first.. The backend.

My Items on ASP.NET Core

If you head over to your Visual Studio for Mac you will see a “Connected App” template. This outputs an iOS and Android app that can talk to a localhost ASP.NET Core application that runs on your macOS machine! Whoa Cool!. Now make sure you have the latest RC4 of .NET Core installed. It isn’t the one on the home page of .NET Core.. it is hidden in a GitHub readme: https://github.com/dotnet/core/blob/master/release-notes/rc4-download.md

If you just want the source code for the app to play around with you can grab it from my GitHub. Now, once we have the source code we can run the site and navigate to /api/item to retrieve the default lists of items:

Linux App Service

Looking good! Next up, Let’s create our Azure App Service that will run on Linux (in preview today). Head to your Azure Portal and hit New -> Web + Mobile + Web App on Linux (preview):

This will go through the standard setup process and bring you in to your standard app service settings. The first thing that we need to do is adjust our Docker Container. We want to select .NET Core v1.0 runtime stack and REALLY REALLY IMPORTANT to set the startup file. This file is the main DLL of our application. We will be uploading our files to the wwwroot.

Build

I decided to throw all of my code in Visual Studio Team Services (VSTS) and do some good DevOps work to make Donovan Brown proud. You could also just put your code on GitHub if you would like and VSTS will also build it. To actually build it, is crazy easy actually, just select ASP.NET Core (PREVIEW).

This literally does everything for you! I have disabled tests and I have my dotnet commands pointing to a subfolder, but that is about it:

Release

Now, let’s publish this thing. The build will give us a zip file to use and normally you would use Web Deploy and done… but that doesn’t work on Linux just yet… and Kudu… not yet.. and all the continuous git stuff… not yet… so let’s FTP the files! In the azure portal you can grab your FTPs user name and password that you will need.

There are 4 steps needed in the release definition:

  1. Stop App Service

  2. Extract Zip File

  3. Upload Files

  4. Start App Service

1, 2, and 4 are easy with minimal config, but #3 you must specify the remote directory of /site/wwwroot

Whoa!! we did it!!

Fun fact… Preview inside of VSTS and the Azure portal in this blog post alone are cased 3 different ways :)

]]>