Saturday, October 25, 2014

Microsoft OWIN: Getting base path for web services (C#)

In my recent post on using OWIN and WebApi, I described how to separate your controllers into a separate DLL. Often the controllers need to call other methods that may need access to the base path of the web service (e.g. the bin folder).

The code below can be used to find that base path from other classes, without having to always pass a path parameter from method to method.

using System;
using System.IO;
using System.Reflection;
namespace ExampleProject
{
public static class OwinUtility
{
public static string BasePath
{
get
{
string basePath = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(basePath);
string fullPath = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(fullPath);
}
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

Thursday, October 23, 2014

OWIN hosting using a Separate WebApi Controller DLL

Here is a bare bones demonstration (4 minutes) showing you how to create a standalone class library of a WebApi controller, then hosting the controller in Microsoft's OWIN (in IIS). This is done using Visual Studio 2013 Update 3.

The video can be watched here: YouTube Watch

The source can be downloaded here: Download Source

What do you think?

Sunday, October 12, 2014

WeightedRandom - Select content based on weights (C# / .NET)

Need to select content from a collection based on weights?  Here is a great .NET 4+ class that is very helpful.

The class can be used with just about any collection and you can pass in a delegate/lamda to determine what the weight is on each collection object.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//
// THIS IS ALL JUST TEST CODE
//
// THE ACTUAL WEIGHTED RANDOM CODE IS IN THE WeightedRandom.cs file
//
namespace PaulTechGuy.Weights
{
class Program
{
class Foo
{
public string Name { get; set; }
public int Weight { get; set; }
public Foo(string name, int weight)
{
Name = name;
Weight = weight;
}
}
static void Main(string[] args)
{
new Program().Run(args);
}
private void Run(string[] args)
{
// test data
Foo[] items = new Foo[]
{
// there are six individual weights from 10 to 60)
new Foo("Sally Target=17% (1/6th)", 10),
new Foo("Fred Target=30% (1/3th)", 30), // or 2/6
new Foo("John Target=50% (1/2th)", 60), // or 3/6
};
// here is the magic; declare your collection Func weight delegate and
// create the WeightedRandom object; after that you just call Next() to
// get your next random object based on weights
Func<Foo, int> fweight = f => f.Weight;
WeightedRandom<Foo> foos = new WeightedRandom<Foo>(items, fweight, new Random());
// spit out a bunch of test results
for (int times = 0; times < 5; ++times)
{
// generate a bunch of random test data and store counts
Dictionary<string, int> statistics = new Dictionary<string, int>();
for (int i = 0; i < 1000; ++i)
{
Foo foo = foos.Next();
if (!statistics.ContainsKey(foo.Name))
{
statistics.Add(foo.Name, 0);
}
statistics[foo.Name] += 1;
}
// print out results
double total = statistics.Sum(s => s.Value);
foreach (var kvp in statistics)
{
Console.WriteLine("{0} => {1} (Actual {2}%)", kvp.Key, kvp.Value, Math.Round(kvp.Value / total * 100));
}
Console.WriteLine();
}
}
}
}
view raw Program.cs hosted with ❤ by GitHub
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
namespace PaulTechGuy.Weights
{
public class WeightedRandom<T>
{
private readonly List<IGrouping<int, T>> _itemMap;
private readonly Random _random;
private readonly int _maxWeight;
public WeightedRandom(T[] items, Func<T, int> weight, Random rnd)
{
Contract.Requires(items.Length > 0);
_random = rnd;
// map the items by weight and sort by weight
_itemMap = items
.GroupBy(weight)
.OrderBy(g => weight)
.ToList();
// weights are sorted in ascending order; max weight will be last element
_maxWeight = _itemMap.ElementAt(_itemMap.Count - 1).Key;
}
public T Next()
{
// select a random weight
int randomWeight = _random.Next(_maxWeight + 1);
// get the first group where our random weight is less then element weight
IGrouping<int, T> items = _itemMap
.FirstOrDefault(b => randomWeight <= b.Key);
// since we based our randomWeight on the maxWeight, we better have found one
if (items == null)
{
throw new InvalidOperationException("Internal bug: should have found at least the maxWeight element");
}
// there may be more than one element with this weight; take a random one
T item = items.ElementAt(_random.Next(items.Count()));
return item;
}
}
}

Can't RDP? How to enable / disable virtual machine firewall for Azure VM

Oh no!  I accidentally blocked the RDP port on an Azure virtual machine which resulted in not being able to log into the VM anymore.  I did ...