Tag Archives: Data

Asp.Net Core 2.0 – Passing data into a Model Using DI

Imagine you have an Asp.Net Core web page, and you would like to edit some data in a form, but you’d like to default that data to something (maybe initially specified in the Web.Config).

I’m sure there’s dozens of ways to achieve this; but this is one.

Let’s start with a bog standard MVC web app:

Step one is to define a model in which to hold your data; here’s mine:

public class CurrentAppData
{
    public string DataField1 { get; set; }
}

Let’s register that in the IoC container:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });
 
 
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
 
    services.AddTransient<CurrentAppData, CurrentAppData>(
        a => new CurrentAppData()
        {
            DataField1 = "test value"
        });

Next thing we’ll need is a View, and a corresponding view model to edit our data; here’s the view:

@model EditDataViewModel
@{
    ViewData["Title"] = "Edit Data";
}
 
<h2>@ViewData["Title"]</h2>
 
<div>
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
 
</div>

And now the view model (that is, the model that is bound to the view):

public class EditDataViewModel
{
    public EditDataViewModel(CurrentAppData editData)
    {
        EditData = editData;
    }
    public CurrentAppData EditData { get; set; }
}

The final step here is to adapt the controller so that the CurrentAppData object is passed through the controller:

public class EditDataController : Controller
{
    private readonly CurrentAppData _currentAppData;
 
    public EditDataController(CurrentAppData currentAppData)
    {
        _currentAppData = currentAppData;
    }
 
    public IActionResult EditData()
    {
        return View(new EditDataViewModel(_currentAppData));
 
 
    }
}

That works as far as it goes, and we now have the data displayed on the screen:

The next step is to post the edited data back to the controller; let’s change the HTML slightly:

<form asp-action="UpdateData" asp-controller="EditData" method="post" enctype="multipart/form-data">
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
    <br />
    <button type="submit" class="btn-default">Submit Changes</button>
</form>

We’ve added a submit button, which should cause the surrounding form element to execute whichever “method” it’s been told to (in this case, POST). It will look for an action on the controller called UpdateData, so we should create one:

public IActionResult UpdateData(EditDataViewModel editDataViewModel)
{
    System.Diagnostics.Debug.WriteLine(editDataViewModel.EditData.DataField1);
    return View("EditData", editDataViewModel);
}

Here, we’re accepting the EditDataViewModel from the view. However; when we run this, we get the following error:

Error:

InvalidOperationException: Could not create an instance of type ‘WebApplication14.Models.EditDataViewModel’. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the ‘editDataViewModel’ parameter a non-null default value.

Let’s first implement a fix for this, and then go into the whys and wherefores. The fix is actually quite straightforward; simply give the view model a parameterless constructor:

public class EditDataViewModel
{
    public EditDataViewModel()
    {
        
    }
 
    public EditDataViewModel(CurrentAppData editData)
    {
        EditData = editData;
    }
    public CurrentAppData EditData { get; set; }
}

The problem that we had here is that the `EditDataViewModel` that is returned to UpdateData is a new instance of the model. We can prove this by changing our code slightly:

Here, we’ve added a field called TestField1 to the model, and populated it just before we pass the model to the view; and on the post back, it’s gone. I’m not completely sure why the view model can’t be created by the middleware in the same way that the controller is; but that’s the subject of another post.

Finally, show the value back to the screen

To wrap up, we’ll just show the same value back to the screen; we’ll add an extra value to the model:

public class CurrentAppData
{
    public string DataField1 { get; set; }
 
    public string DisplayField1 { get; set; }
}

And we’ll just display it in the view:

<form asp-action="UpdateData" asp-controller="EditData" method="post" enctype="multipart/form-data">
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
    <br />
    <button type="submit" class="btn-default">Submit Changes</button>
    <br />
    <label>@Model.EditData.DisplayField1</label>
    <br />
</form>

Finally, we’ll copy that value inside the controller (obviously, this is simulating something meaningful happening), and then display the result:

public IActionResult UpdateData(EditDataViewModel editDataViewModel)
{
    editDataViewModel.EditData.DisplayField1 = editDataViewModel.EditData.DataField1;
    return View("EditData", editDataViewModel);
}

Let’s see what that looks like:

Playing with Azure Event Hub

I’ve recently been playing with the Azure Event Hub. This is basically a way of transmitting large amounts* of data between systems. In a later post, I may try and test these limits by designing some kind of game based on this.

As a quick disclaimer, it’s worth bearing in mind that I am playing with this technology, and so much of the content of this post can be found in the links at the bottom of this post – you won’t find anything original here – just a record of my findings. You may find more (and more accurate) information in those.

Event Hub Namespace

The first step, as with many Azure services, is to create a namespace:

For a healthy amount of data transference, you’ll pay around £10 per month.

Finally, we’ll create event hub within the namespace:

When you create the event hub, it asks how many partitions you need. This basically splits the message delivery; and it’s clever enough to work out, if you have 3 partitions and two listeners that one should have two slots, and one, one slot:

We’ll need an access policy so that we have permission to listen:

New Console Apps

We’ll need to create two applications: a producer and a consumer.

Let’s start with a producer. Create a new console app and add this NuGet library.

Here’s the code:

class Program
{
    private static EventHubClient eventHubClient;
    private const string EhConnectionString = "Endpoint=sb://pcm-testeventhub.servicebus.windows.net/;SharedAccessKeyName=Publisher;SharedAccessKey=key;EntityPath=pcm-eventhub1";
    private const string EhEntityPath = "pcm-eventhub1";
 
    public static async Task Main(string[] args)
    {
        EventHubsConnectionStringBuilder connectionStringBuilder = new EventHubsConnectionStringBuilder(EhConnectionString)
        {
            EntityPath = EhEntityPath
        };
 
        eventHubClient = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString());
 
        while (true)
        {
            Console.Write("Please enter message to send: ");
            string message = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(message)) break;
 
            await eventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes(message)));
        }
 
        await eventHubClient.CloseAsync();
 
        Console.WriteLine("Press ENTER to exit.");
        Console.ReadLine();
    }
}

Consumer

Next we’ll create a consumer; so the first thing we’ll need is to grant permissions for listening:

We’ll create a second new console application with this same library and the processor library, too.

class Program
{
    private const string EhConnectionString = "Endpoint=sb://pcm-testeventhub.servicebus.windows.net/;SharedAccessKeyName=Listener;SharedAccessKey=key;EntityPath=pcm-eventhub1";
    private const string EhEntityPath = "pcm-eventhub1";
    private const string StorageContainerName = "eventhub";
    private const string StorageAccountName = "pcmeventhubstorage";
    private const string StorageAccountKey = "key";
 
    private static readonly string StorageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", StorageAccountName, StorageAccountKey);
 
    static async Task Main(string[] args)
    {
        Console.WriteLine("Registering EventProcessor...");
 
        var eventProcessorHost = new EventProcessorHost(
            EhEntityPath,
            PartitionReceiver.DefaultConsumerGroupName,
            EhConnectionString,
            StorageConnectionString,
            StorageContainerName);
 
        // Registers the Event Processor Host and starts receiving messages
        await eventProcessorHost.RegisterEventProcessorAsync<EventsProcessor>();
 
        Console.WriteLine("Receiving. Press ENTER to stop worker.");
        Console.ReadLine();
 
        // Disposes of the Event Processor Host
        await eventProcessorHost.UnregisterEventProcessorAsync();
    }
}

class EventsProcessor : IEventProcessor
{
    public Task CloseAsync(PartitionContext context, CloseReason reason)
    {
        Console.WriteLine($"Processor Shutting Down. Partition '{context.PartitionId}', Reason: '{reason}'.");
        return Task.CompletedTask;
    }
 
    public Task OpenAsync(PartitionContext context)
    {
        Console.WriteLine($"SimpleEventProcessor initialized. Partition: '{context.PartitionId}'");
        return Task.CompletedTask;
    }
 
    public Task ProcessErrorAsync(PartitionContext context, Exception error)
    {
        Console.WriteLine($"Error on Partition: {context.PartitionId}, Error: {error.Message}");
        return Task.CompletedTask;
    }
 
    public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
    {
        foreach (var eventData in messages)
        {
            var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
            Console.WriteLine($"Message received. Partition: '{context.PartitionId}', Data: '{data}'");
        }
 
        return context.CheckpointAsync();
    }
}

As you can see, we can now transmit data through the Event Hub into client applications:

Footnotes

*Large, in terms of frequency, rather than volume – for example, transmitting a small message twice a second, rather than uploading a petabyte of data

References

https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-dotnet-standard-getstarted-send

https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-dotnet-standard-getstarted-receive-eph

Creating Complex Tables using SQLite.Net

Based on this earlier post, I returned to my test project to find that it didn’t actually pass anymore. The first issue was that the test couldn’t locate Sqllite3.dll.

Thanks to this question on every programmers favourite web site, I realised that I needed to add an extension for SQLite.

The next issue was when I tried to add a test to create a complex table:

complex1

Don’t know about [EntityName].

What I mean by a complex table, and the thing that CreateTable doesn’t like, is an entity that references another entity (the same is true if you try to reference the same entity).

Finally, you’re not allowed to use the System.Object type:

Complex2

A fix

It is my understanding that, if you can get it to work with SQLite, Entity Framework will solve this problem for you. I took more of a roll-your-own approach. The key issue here is that you want SQLite to not try to serialise the second object; and for this, you can use the [Ignore] attribute:

private ProductCategory _category;
 
[Ignore]
public ProductCategory Category
{
    get { return _category; }
    set
    {
        _category = value;
        RaisePropertyChanged();
    }
}

So, that stops it crashing. The next part is largely dependent on your data: if you have a basic primary / foreign key one-to-n mapping then this will work; however, anything more complex, and you’ll probably have to write a custom abstraction for the data. All that said, my solution starts with a base entity class:

public abstract class BaseDataEntity : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
 
    public abstract string Key { get; set; }
}

The PropertyChanged goes without saying (it’s like the roads), but the interesting part is the Key. Based on the code above, each entity needs a uniquely identifiable key; in this case, it’s a string; however, this can be any primitive type. In the derived class, you’ll need to map the type to the data; for example:

 
[Ignore]
public ProductCategory Category
{
    get { return _category; }
    set
    {
        _category = value;
        RaisePropertyChanged();
    }
}
 
public string CategoryRef
{
    get { return Category.Key; }
    set
    {
        if (Category == null)
        {
            Category = new ProductCategory()
            {
                Key = value
            };
        }
    }
}        

I’ll explain CategoryRef later on.

The next thing is to put some logic into the data access (I simply created a DataAccessBase class to sit on top of the SQLite data manipulation. Here is the abstraction to add a record:

 
public void Add(Type objType, object t)
{
    _connection.Insert(t);
 
    // Look for any ignored properties
    var ignored = objType                
        .GetProperties().Where(p =>
            p.CustomAttributes.Any(a => a.AttributeType == typeof(SQLite.Net.Attributes.IgnoreAttribute)));
 
    // For each, look for a reference
    foreach (var p in ignored)
    {
        // Determine the type first and get the value
        Type propertyType = p.PropertyType;
        var propertyValue = p.GetValue(t);
 
        // Recursively call this function to add the reference
        Add(propertyType, propertyValue);
    }
}

As you can see, for each reference, it simply recursively calls itself to add that, too. This will spectacularly fall down if you have a circular reference (so don’t do that, or don’t use this if you do).

Next is the Get:

 

public T Get<T>(string key) where T : class
{
    T data = _connection.Get<T>(key);
 
    var ignored = typeof(T)
        .GetProperties()
        .Where(p => p.GetCustomAttributes(typeof(SQLite.Net.Attributes.IgnoreAttribute), inherit: true).Any())
        .ToList();
 
    // For each, look for a reference
    foreach (var p in ignored)
    {
        // Get the reference property
        string propName = $"{p.Name}Ref";
        PropertyInfo refProp = typeof(T).GetProperty(propName);
 
        // Get its value (we know it's a string)
        string val = refProp.GetValue(data).ToString();
 
        // Determine the type first and get the value
        Type propertyType = p.PropertyType;
        
        var mapping = _connection.TableMappings.First(m => m.MappedType == propertyType);
        var rec = _connection.Find(val, mapping);
 
        // Update the property
        p.SetValue(data, rec);
 
    }
}

Here, I’m using a convention based approach; so, where I reference a separate class, I also have separate property called [Class]Ref; which you can see earlier on in the example of the entity code.

Conclusion

And that’s it; I make no assertions about edge cases, but for basic data that references other basic data, this works fine.

Acknowledgements

I have a great deal of help in creating this, but mainly just from random search results; however, I did ask a question on Stack Overflow

SQL Server quick insert test data

I recently came across a little known feature of SSMS that made me think that, for small amounts of data, it may be possible to create a procedure to insert test data into a table. Let’s start with the table:

CREATE TABLE [dbo].[Audit](
	[AuditDate] [datetime] NOT NULL,
	[AuditText] [varchar](max) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

So, let’s create a statement that will inset data into this table:

INSERT INTO DBO.[Audit]
(AuditDate, AuditText)
VALUES
(GETDATE(), 'The sky is blue')

GO

sql1

Okay, so here’s the thing; try this:

INSERT INTO DBO.[Audit]
(AuditDate, AuditText)
VALUES
(GETDATE(), 'The sky is blue')

GO 10

sql2

So, that’s good, but what if you want some actual kosher data?

Randomising a date is relatively easy, using a combination of the RAND() function and the DATEADD() functions, you can do this in a single line. However, randomising text is more complex. If you just want random strings of letters, then you could try something like this. However, if you want something more sensible, then you can use a lookup table:

DECLARE @lookupTable TABLE (TextLookup VARCHAR(255))
DECLARE @lookupTableSize INT

INSERT INTO @lookupTable
(TextLookup)
VALUES
('red'), ('blue'), ('green'), ('orange'), ('purple')

SELECT @lookupTableSize = COUNT(1) FROM @lookupTable

INSERT INTO dbo.[Audit]
(AuditDate, AuditText)
VALUES
(DATEADD(day, -ABS(CHECKSUM(NewId())) % 30000, GETDATE()),
(SELECT TOP 1 TextLookup FROM (
    SELECT TextLookup, ROW_NUMBER() OVER (ORDER BY TextLookup) AS RowNum
    FROM @lookupTable
) AS DerivedAudit
WHERE DerivedAudit.RowNum >= (ABS(CONVERT(BIGINT,CONVERT(BINARY(8), NEWID()))) % @lookupTableSize) + 1))

GO 100


SELECT *
FROM dbo.Audit

It’s worth noting that GO in this case executes the entire script, not just the bit you want; however, I’m not proposing you use this for any serious volume – just for add a quick few records.

Implementing single cell copy and full row Item Selection in WPF DataGrid

Recently, I came across a strange problem with a DataGrid while using the MVVM-Light pattern. The problem was that I needed to implement two, seemingly similar pieces of functionality:

1. To copy any given cell in the data grid
2. To search the database, based on a specific piece of data in the selected row of the datagrid (regardless of which cell was selected).

To implement the Copy feature was unbelievably easy – you don’t even need a custom command; just add the following setting to the DataGrid:

SelectionUnit ="CellOrRowHeader"

And the following context menu:

<DataGrid.ContextMenu>
    <ContextMenu>                    
       <MenuItem Command="Copy"/>                    
    </ContextMenu>
</DataGrid.ContextMenu>

And the copy is done!

So, next, I wanted to implement the custom search. I needed to identify the currently selected row in my ViewModel, so I added a new property:

        private MyDataClass _selectedItem;
        public MyDataClass SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                RaisePropertyChanged(() => SelectedItem);
            }
        }

I then bound this to the selected item of the datagrid, like this:

     < DataGrid ItemsSource ="{ Binding Path =MyDataCollection}"                   
                  SelectedItem="{ Binding Path =SelectedItem}"                   
                  SelectionUnit ="CellOrRowHeader"  
&#91;/sourcecode&#93;

And finally, created my command:

&#91;sourcecode language="csharp"&#93;
         public RelayCommand MyCommand { get ; private set ; }
&#91;/sourcecode&#93;

In the constructor, initialised it:

&#91;sourcecode language="csharp"&#93;
     this.MyCommand = new RelayCommand (() => this.MyCommandFunc());

Created the function:

         private void MyCommandFunc()
        {
            QueryDB(SelectedItem.ValueOne);
        }         

And, finally, setup the context menu:

<DataGrid.ContextMenu>
    <ContextMenu>                    
         <MenuItem Command ="Copy"/>                    
         <MenuItem Header ="My Funky Command" Command="{Binding MyCommand}"/>
    </ContextMenu>
</DataGrid.ContextMenu>

But this didn’t work! (Queue dramatic music).

The problem is down to this:

SelectionUnit ="CellOrRowHeader"

So, change it to:

SelectionUnit="FullRow" 

And it works again… but now copy doesn’t work, because it copies the FULL ROW!

So, the two features are incompatible?

I did find a workaround which doesn’t breach the separation of concerns. Please note that, although this does work, and does not breach separation of concerns, it may or may not be the best way of doing it. If you have, or know of, a better way the PLEASE leave a comment, or mail me and let me know.

The Workaround

Instead of binding the SelectedItem property, bind the Tag property of the grid:

< DataGrid ItemsSource ="{ Binding Path =MyDataCollection}" Tag="{ Binding Path =SelectedItem}" SelectionUnit ="CellOrRowHeader" [/sourcecode] Now, we need a little code-behind, which must remain agnostic to the ViewModel: [sourcecode language="csharp"] private void DataGrid_SelectedCellsChanged( object sender, SelectedCellsChangedEventArgs e) { (( DataGrid)sender).Tag = ((DataGrid)sender).SelectedCells.FirstOrDefault().Item; } [/sourcecode] Now, because the SelectedItem is bound in the view to the Tag, updating the Tag, updates the SelectedItem. This means that when you call your function (as described above): [sourcecode language="csharp"] private void MyCommandFunc() { QueryDB(SelectedItem.ValueOne); } [/sourcecode] SelectedItem is now set. Conclusion

Whilst I can see why this works the way it does, it doesn’t seem sensible that I need to jump through so many hoops to get this to work without breaking the separation of concern. It may just be a quirk with the DataGrid, but it feels like a hack – which I don’t like. Nevertheless, ATM it’s the only solution that I can come up with that doesn’t mean directly referencing the View from the ViewModel.

Implementing a call to search using MVVM Light

I recently started using the MVVM Light framework to create an app. One of the first things that I found tripped me up was trying to link the ViewModel functionality with the visual interface. After a little more searching than should be necessary I came across the concept of commands. Basically, thos allows you to bind the functionality of your view model to an action on the screen. In the example below it’s the action of clicking a button.

First, create a new relay command (this is in the namespace GalaSoft.MvvmLight.Command):

    public class MainViewModel : ViewModelBase
    {
        private readonly IDataService _dataService;

        /// <summary>
        /// The <see cref="WelcomeTitle" /> property's name.
        /// </summary>
        public const string WelcomeTitlePropertyName = "WelcomeTitle" ;

        private string _welcomeTitle = string.Empty;

               // New Command Variable
        public RelayCommand SearchCommand { get ; private set ; }
        ...

Next initialise the command in the constructor of the VM:

        public MainViewModel( IDataService dataService)
        {
            this.SearchCommand = new RelayCommand (this.GetDataCount);
            ...

Obviously, the execute function must exist. For example:

        private void GetData()
        {
                _dataservice.GetData((count, error) =>
                {
                    if (error != null)
                    {
                        // Report error here
                        return;
                    }

                    // Do something with data here
                });
        }

Finally, simply add a call from the XAML in MainWindow:

Parameters

You can also pass parameters, by simply providing the CommandParameter attribute and then using it. However, given that you’re already in the databound context (i.e. you’re function is in your ViewModel, which is bound to the DataContext) I didn’t find a need for this, as it’s possible to simply reference the property directly.

Conclusion

This ends up being quite a neat way to link the two. The screen is linked to the view model without having a chunk of code in the button click handler.