Stock Alerts Update 2019.07.03

I’d been meaning to get this update out over the weekend, but a stomach bug visited our house and threw off my schedule. I’d like to get these updates out about once a week going forward, but since this is a side project and I’m working on it for fun in my off hours, I’m not going to sweat it too much.

Also, as I mentioned in my first post, these updates will be pretty informal and unpolished. I just want to talk in detail about some of the things I did in the past week on the project, and what I plan to do in the coming week.

Last Week


With my announcement last weekend that I’ll be building Stock Alerts in public, I was compelled to write a few extra posts to lay some of the groundwork for project. I wrote the introductory post, spoke about the features, and laid out the infrastructure.

Naturally, this took some of my time away from development, but I think it was time well spent.

I have other posts that I want to write in the future to cover some of the work I’ve already done (particularly in the API), and I’ll try to work those in in the coming weeks without sacrificing too much dev time.

Create Alert Definition – Stock Search

I’ve been working on the Create Alert Definition screen in the Stock Alerts mobile app. This is where the user defines an alert, including selecting the stock and defining the alert criteria. Specifically, I was focused on the stock selection functionality last week (we’ll talk more about building the alert criteria in a couple weeks).

Here’s a wireframe for these screens:

Stock Alerts Create Alert Definition screen wireframes

I want the stock search feature to function like a typeahead search, allowing the user to type as much or as little of the stock symbol or company name as desired, and when they pause, the system retrieves the search results.

I already had an API endpoint for finding stocks based on a search string; I just needed to add CancellationToken support, which was as simple as adding it to the Azure function signature and plumbing it down to the data access layer:

public async Task<IActionResult> FindStocksAsync(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "stocks")] HttpRequest req,
    CancellationToken cancellationToken,
    ILogger log)

Implementing search on the mobile app side took a bit more work…

Thinking about this from an implementation perspective, my StockSearchPageViewModel needs to have a SearchString property that receives the input from the textbox, waits a second, and if there’s no additional input, execute the web request to get the search results from the API, which will populate a collection of results on the view model to which the view is bound. If additional input is received from the user while the web request is executing, we need to cancel it and issue a new request.

I can’t (shouldn’t) implement all of this in the SearchString property setter, because you can’t (and shouldn’t want to) make a property setter async. Property setters should be fast and non-blocking. And yet I want to be able to simply bind the Text property of my search box to a property on my view model.

I ended up using NotifyTask from Stephen Cleary’s Nito.Mvvm.Async library, which contains helpers for working with async methods in MVVM. NotifyTask is “essentially an INotifyPropertyChanged wrapper for Task/Task<T>,” as Stephen writes in this SO answer, which helped me quite a bit (the answer refers to NotifyTaskCompletion, which was replaced by NotifyTask).

So here’s my StockSearchPageViewModel implementation:

public class StockSearchPageViewModel : ViewModelBase
    private readonly IStocksService _stocksService;
    private CancellationTokenSource _searchCancellationTokenSource;

    public StockSearchPageViewModel(
        IStocksService stocksService,
        INavigationService navigationService, 
        ILogger logger) : base(navigationService, logger)
        _stocksService = stocksService ?? throw new ArgumentNullException(nameof(stocksService));

    private string _searchString;
    public string SearchString
        get => _searchString;
            _searchString = value;

            var newSearchCancellationTokenSource = new CancellationTokenSource();
            if (_searchCancellationTokenSource != null)
            _searchCancellationTokenSource = newSearchCancellationTokenSource;

            Stocks = NotifyTask.Create(SearchStocksAsync(_searchCancellationTokenSource));

    private NotifyTask<List<Stock>> _stocks;
    public NotifyTask<List<Stock>> Stocks
        get => _stocks;
            _stocks = value;

    private Stock _stock;
    public Stock SelectedStock
        get => _stock;
            _stock = value;
            var navigationParams = new NavigationParameters();
            navigationParams.Add(NavigationParameterKeys.SelectedStock, _stock);

    private async Task<List<Stock>> SearchStocksAsync(CancellationTokenSource searchCancellationTokenSource)
        if (SearchString.Length >= 1)
            await Task.Delay(1000, searchCancellationTokenSource.Token);
                if (!searchCancellationTokenSource.IsCancellationRequested)
                    var stocks = await _stocksService.FindStocksAsync(SearchString, searchCancellationTokenSource.Token);
                    return stocks.ToList();
                _searchCancellationTokenSource = null;

        return new List<Stock>();

The view model creates and manages the cancellation token source, and cancels it when necessary, in the SearchString property setter. This is also where we create the NotifyTask, passing it a delegate for the SearchStocksAsync(..) method, which delays one second and calls the search API. The results of the SearchStocksAsync(..) method call are exposed as NotifyTask<List<Stock>> by the Stocks property.

In my StockSearchPage view, I can simply bind to the properties, like so:

<SearchBar Grid.Row="1" Placeholder="Start typing ticker or company name" Text="{Binding SearchString, Mode=TwoWay}"></SearchBar>
<ListView Grid.Row="2" ItemsSource="{Binding Stocks.Result}" SelectedItem="{Binding SelectedStock}">

… and with that, the typeahead stock search seems to be working pretty well.


ASP.Net Core 2.1 introduced HttpClientFactory, which solves some of the problems developers run into when they create too many HttpClients in their projects. Steven Gordon has a nice write-up on HttpClientFactory and the problems it attempts to solve here.

The syntax to configure clients using HttpClientFactory is straightforward. In your ASP.NET Core Startup.cs:

services.AddHttpClient(Apis.SomeApi, c =>
    c.BaseAddress = new Uri("");
    c.DefaultRequestHeaders.Add("Accept", "application/json");

Unfortunately, since Xamarin.Forms projects target .NET Standard, we can’t use any of the .NET Core goodies like HttpClientFactory. I wanted a similar pattern for configuring and creating my HttpClients in the mobile app, so I took some inspiration from here and created my own poor man’s HttpClientFactory.

Here’s my IHttpClientFactory interface:

public interface IHttpClientFactory
    void AddHttpClient(string name, Action<HttpClient> configurationAction);

    HttpClient CreateClient(string name);

And here’s my fairly naïve, yet adequate implementation:

public class HttpClientFactory : IHttpClientFactory, IDisposable
    private readonly IDictionary<string, Action<HttpClient>> _configurations = new Dictionary<string, Action<HttpClient>>();
    private readonly IDictionary<string, HttpClient> _clients = new Dictionary<string, HttpClient>();

    public void AddHttpClient(string name, Action<HttpClient> configurationAction)
        if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name), $"{nameof(name)} must be provided.");
        if (_configurations.ContainsKey(name)) throw new ArgumentNullException(nameof(name), $"A client with the name {name} has already been added.");

        _configurations.Add(name, configurationAction);

    public HttpClient CreateClient(string name)
        if (!_clients.ContainsKey(name))
            if (!_configurations.ContainsKey(name)) throw new ArgumentException($"A client by the name of {name} has not yet been registered.  Call {nameof(AddHttpClient)} first.");

            var httpClient = new HttpClient();
            _clients.Add(name, httpClient);

        return _clients[name];

    public void Dispose()
        foreach (var c in _clients)

Finally, the registration of the factory with a single client in my App.xaml.cs:

IHttpClientFactory httpClientFactory = new HttpClientFactory();
    c =>
        c.BaseAddress = new Uri(MiscConstants.StockAlertsApiBaseUri);
        c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

This gives me a nice way to create and manage my HttpClients in my Xamarin.Forms project, and it will be easy to drop in the real HttpClientFactory if it ever becomes available for Xamarin.Forms projects.

Last week’s activities also included implementing a web service client base class for handling common tasks when communicating with the API, storing access and refresh tokens on the client, and working out my unauthorized/refresh token flow, but those are topics for another post. This one’s long enough.

This Week

This week’s already about half over, and we’ve got the 4th of July coming up. I plan to continue working on the Create Alert Definition screen, and perhaps by the next time I write I’ll have the functionality for building the alert criteria and saving the alert definition working – we’ll see.

Here’s the repository for the project if you’d like to follow along:

Thanks for reading, and Happy Fourth of July!


If you’d like to receive new posts via e-mail, consider joining the newsletter.

Stock Alerts Features

In my previous post I revealed my new side project, Stock Alerts, and my intention to build a .NET Core product on the Azure stack, posting regular updates about my work as I go. Before I get down into the weeds in future posts, I thought it might be good to first talk at a higher level about the MVP features I’ll be implementing and the infrastructure that will be needed.


Stocks Alerts will consist of a mobile app with a small number of key features. Of course there will be backend services to support the mobile app functionality, but we’ll talk about the features from the user’s perspective as he/she interacts with the app.

There will also be a web app eventually, but for now we’ll just focus on the mobile app.

Alert Definition Management

Push notificationStock Alerts users will be able to view, create, edit, and delete alert definitions that define the criteria for a stock alert. In the course of creating an alert definition, the user will search for and select a stock, name the alert, and define the criteria that will trigger the alert.

Initially, the set of stocks available to create alert definitions will be limited, due to daily API call limits set by my data provider (which I’ll talk in a future post). I’ve considered either supporting only stocks in the S&P 500 at first or allowing the initial users to essentially define the initial universe of stocks by the alert definitions that they create. Still thinking on this one…

For the alert criteria, the API will support allowing the user to choose from multiple rule types (like various price alerts, technical alerts, and fundamental alerts), as well as combining multiple rules into a boolean logic tree, but for MVP the mobile app will only expose the ability to enter 1..n price alerts combined by an AND or OR.

Alert Notifications

Azure FunctionsThe Stock Alerts backend will evaluate all active alert definitions as it receives new stock data and notify users of triggered alerts via one or more of three methods: push notification, e-mail, and/or SMS message.

The processing of active alert definitions and the sending of notifications via the three channels will be handled by Azure Functions in conjunction with Azure Service Bus queues. Azure Functions are well-suited for these types of tasks – I pay for the compute that I use and they can scale out under load (for example, when AAPL makes a large move and triggers a large number of alerts).

User Registration & Login

The Stock Alerts mobile app will allow new users to register with the app and existing users to login. To register, a user just needs to provide their e-mail address, a unique username, and their password. After login, web requests will be authenticated via token-based authentication

User Preferences Management

Users will be able to set their notification preferences in the Stock Alerts app, including the channels that they will be notified on (push notification, e-mail, or SMS), as well as their e-mail address and SMS phone number, if applicable.

Payment/Subscription Management

Stripe logoThough users will be able to register and set up a limited number of alert definitions for free, I’ll charge users who have more than a few active alert definitions. Stripe is the standard for managing subscriptions and taking online payments, and their API is well-designed. We’ll integrate with Stripe to manage user subscriptions and payments for premium users.


Xamarin FormsThe mobile app will target both Android and iOS (and eventually web), and we’ll use Xamarin.Forms to accomplish this. I’m an Android user, so Android will be the first platform I focus on. I can get idea validation and feedback by launching on a single platform, and if there is traction after launch and I want to expand to iOS, I’ll be well-positioned to do so having build the app with Xamarin.Forms.

A web app will probably be post-MVP as well.

Is That All?

The feature set that I’m targeting for MVP is extremely limited by design. There’s enough here to provide value, prove out the idea, and demonstrate interactions throughout the full stack while being small enough to complete within a couple of months at 5-10 hours per week (though writing about it will slow me down some). There will also be plenty of opportunities for enhancements and additional features post-MVP, if I’m so inclined.

When choosing a side project, it’s important to me that it be very small and limited in scope for a few reasons. First, I want something that I can build quickly while I’m motivated and energized about the new idea and lessen the risk of losing interest or becoming bored with it halfway through. I also want to launch as soon as possible to begin the feedback loop and start learning from my users: What do they like/not like? How do they use the product? Will they pay for it? Etc… Finally, by limiting the initial feature set, I focus on just the core features of the product and I don’t waste time building features that my users may not even care about.

So now that we know what features we’ll be building, we’re ready to talk about the infrastructure needed to support those features!

… but that’s a topic for my next post. Thanks for reading.


If you’d like to receive new posts via e-mail, consider joining the newsletter.

Working on a New Side Project in Public

For the past month or so I’ve been working on a new side project. It’s a small project that will allow me to exercise existing skills, re-sharpen older skills that I’ve not used in awhile, and learn some new ones.

I’d like to share it with you…

Working in Public

I’ve been working my side project every weekday morning for an hour or two before my workday starts and on the occasional weeknight or weekend. I toil away mostly in solitude, except when I solicit feedback or ask for advice from a colleague and buddy who’s working on his own project.

I’ve recently been inspired by a few folks on various podcasts to start working in public. They speak of the benefits of sharing what you’re learning, developing, building with your audience as you’re working on it, an idea that strikes fear in the hearts of those who, like me, are inclined towards self-conscious perfectionism. It’s difficult to put your in-progress work out there for all to see, warts and all.

There’s been an increasing trend towards working in public, particularly among indie makers and developers. I dipped my toe into those waters with my last project, Open Shippers, earlier this year*, and I plan to get back in the pool with this project.

My plan is to post fairly regular (weekly?) updates about what I’m doing on the project:

  • What did I do the prior week?
  • Is there a particular problem I solved, pattern I used, or trick I learned that is worth sharing?
  • What do I plan to work on in the coming week?
  • Any particular challenges worth mentioning?

Things like that.

These will be pretty rough, unpolished posts. Sometimes a particular topic I encounter will be worthy of becoming a more in-depth, polished post, and put these up from time to time.


So what are my goals with working on this new project, and doing so in public?

  • Get into the habit of writing regularly.
  • Sharpen old skills and learn new ones.
  • Share what I’m working on and what I’ve learned. Hopefully it is helpful to someone.
  • Demonstrate the process of taking a product from concept to market.
  • Demonstrate well-architected, working product on the Azure / .NET Core stack.
  • Teach.
  • Learn.
  • Have fun.
  • Make some lunch money if anyone subscribes to the service.

What’s the Project?


The idea is not particularly novel or interesting, but it’s a good candidate for what I’m trying to achieve with this project.

I’m building a stock alerts app (hereafter referred to as Stock Alerts until I think of a good name for it) that will allow the user to create an alert definition for a given stock based on a set of criteria that they define. When the alert is triggered, the user will be notified according to their preferences by push notification, SMS, and/or e-mail.

“Aren’t there a ton of other stock alert apps out there?” Yes, there are. Some just let you set a simple price alert; others offer many more features. I plan to support complex alert criteria that include not only simple price alerts, but eventually also technical and fundamental alerts as well, which will differentiate the app from a portion of the market.

I also want to challenge the idea that you have to have a completely novel idea to succeed in building an app that people will pay for. There’s room for multiple competitors in most markets, and oftentimes your app will be the right choice for a segment of the market that’s not currently being served well.

To be clear, I have no illusions of replacing my income with this app, but it will be great fodder for achieving the goals I mentioned above, and it should be a fun little project.


Here’s the some of the technology I’m using:

Current Status

The backend API is coded and running in Azure. I’ll share more detail about the API and how it’s built in future posts, including the overall architecture. I’ve been working on the mobile app for about a week now. I’m able to register/login through the mobile app and display my current alert definitions. Last week I put together some UI wireframes for the Create Alert Definition screens, and I’ll be working on implementing those screens this week.

Wrapping Up

In the spirit of working in public, I’ve made the Stock Alerts repository public: As with most projects, there are areas of the codebase that need some work and refinement, but we’ll address those things together down the road.

Thanks for reading! Until next time,


(* After spending several months working on Open Shippers, I was burned out on it by the time I launched it in preview in February. I failed to differentiate it from other similar services out there, and I didn’t have any gas left in the tank to work on building an audience and making it successful. Someday I may do a post-mortem on the project. Open Shippers wasn’t a total failure though – I learned quite a bit while working on it, particularly about ASP.NET Core and Blazor, and I’ve reused several things I developed for Open Shippers in more recent projects. The site is still live, and I may revive efforts around it at some point, but I’m content to work on something else for the time being.)

If you’d like to receive new posts via e-mail, consider joining the newsletter.

Side Project

It’s been awhile since I’ve done any serious side-project work.  I’ve not had the energy or time to work on a personal project since I started working for my current employer almost three years ago, and, honestly, I haven’t felt much of a need.

When I joined my current employer three years ago, any side projects that I had in flight stopped dead in their tracks because – after years of consulting for the state – I was all of sudden working on interesting problems, being challenged daily, playing with cool new technologies, and building something new and innovative.  The needs I had satisfied previously after hours working on side projects (i.e., the desires to create, innovate, and learn new things) were now being satisfied at work.

I’ve got a bit more free time these days, and while I’m still being challenged at work, I’ve been looking for a project that I can spend some free time on with a few goals in mind:

  • Sharpen my skills on familiar (to me) tech
  • Work on new problems
  • Create something neat (and perhaps profitable)
  • Learn some new (to me) tech when appropriate

I’ve got some ideas for my next project(s).  I’m not ready to reveal what they are yet, but here’s a peek at just a few of the things I intend to use/work with in the coming months:

  • Natural language processing
  • Machine learning
  • Azure Service Fabric
  • ASP.Net Core
  • Some sort of API management to support monetization
  • Xamarin.Forms to target iOS/Android/Windows

So why am I sharing this publicly?  A few reasons…

  1. I wish I would have kept a journal of projects that I’ve worked on in the past to serve as my own personal reference for problems I’ve encountered and lessons learned.  This will be that journal.
  2. Communicating what I’m working on helps to sharpen my thoughts and aid in my understanding and retention.
  3. Sharing my progress will help to keep me accountable when my motivation wanes or my progress slows.
  4. It may be helpful to someone out there.  I hope it is.

I will work on this as time and energy permits.  I hope to post somewhat regularly and frequently, but I make no promises.

That said, thank you for joining me on this ride!

– Jon