I'm running with the code below and I can see that one key is created in the table [DataProtectionKeys]
services.AddDataProtection()
.SetApplicationName(dataProtectionSettings.ApplicationName)
.ProtectKeysWithCertificate(serviceCertificate)
.UnprotectKeysWithAnyCertificate(serviceCertificate)
.PersistKeysToDbContext<DataProtectionContext>();
I'm using this database context (am I missing something?):
class DataProtectionContext : DbContext, IDataProtectionKeyContext
{
/// <summary>
/// A recommended constructor overload when using EF Core with dependency injection.
/// </summary>
/// <param name="options"></param>
public DataProtectionContext(DbContextOptions<DataProtectionContext> options)
: base(options) { }
/// <summary>
/// This maps to the table that stores keys.
/// </summary>
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
But, if I change to ApplicationName string value to something else, I don't see that a new key is created
Any idea why or how to fix it so this database table can support multiple application
My application is using EF6 database first approach. All the entities in the database have 2 common properties "CreatedDateTime" and "ModifiedDateTime".
Currently When i do SaveChanges() im explicitly setting these 2 properties based on if i am creating new entity or updating existing entity.
If its a new entity then set both properties else set only ModifiedDateTime property.
I wanted to know if there is a way to implicitly set these 2 properties on Save or update operation?
Update 1
I know i have to override Savechanges() method however the real issue here is SaveChanges needs to have access to these 2 properties. So i only see 2 options here:
1> Use reflection to find if entity has these properties and set it.
2> Modify default T4 generation so that it derives all entities with predefined interface. And this interface will have these 2 properties. SaveChanges() method can check if entity is derived from this interface and set the property.
I defiantly don't want to use option 1 using refection.
Is there any other way or has anyone done this before in DB first approach?
Going with your second approach: Adjust your T4 files to include a reference to an interface (e.g. IChangeTrack):
public interface IChangeTrack
{
/// <summary>
/// When has this entry be created
/// </summary>
[Required]
DateTime CreatedDateTime { get; set; }
/// <summary>
/// When has this entry been modified
/// </summary>
DateTime? ModifiedDateTime { get; set; }
}
Now overwrite your SaveChanges() routine by doing something like this:
/// <summary>
/// Enhance save changes to handle system fields.
/// </summary>
/// <returns></returns>
public override int SaveChanges()
{
HandleChanges();
int changes = base.SaveChanges();
return changes;
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
HandleChanges();
int changes = await base.SaveChangesAsync(cancellationToken);
return changes;
}
private void HandleChanges()
{
ChangeTracker.DetectChanges();
var entries = ChangeTracker.Entries<IChangeTrack>();
if (entries != null)
{
foreach (DbEntityEntry<IChangeTrack> entry in entries)
{
switch (entry.State)
{
case EntityState.Added:
entry.Entity.CreatedDateTime = DateTime.UtcNow
break;
case EntityState.Modified:
entry.Entity.ModifiedDateTime = DateTime.UtcNow;
break;
}
}
}
}
I have already searched some tutorials and even looked pluralsite Introduction to PRISM. However, most examples based on using unity containers and the some lack of information on how to implement this feature with Mef container.
My simple helloworld module is based on web tutorial. My code is the same except I’m stuck only on HelloModule and using Mef, not Unity as tutorial shows:
The main my problem how to initialize my view with my view model. The only working way I have found via experimenting is to initialize view-model in View constructor:
HelloView.xaml.cs
namespace Hello.View
{
[Export]
public partial class HelloView : UserControl, IHelloView
{
public HelloView()
{
InitializeComponent();
Model = new HelloViewModel(this);
}
public IHelloViewModel Model
{
//get { return DataContext as IHelloViewModel; }
get { return (IHelloViewModel)DataContext; }
set { DataContext = value; }
}
}
}
And standard module initialization code:
[ModuleExport(typeof(HelloModule), InitializationMode=InitializationMode.WhenAvailable)]
public class HelloModule : IModule
{
IRegionManager _regionManager;
[ImportingConstructor]
public HelloModule(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void Initialize()
{
_regionManager.Regions[RegionNames.ContentRegion].Add(ServiceLocator.Current.GetInstance<HelloView>());
}
}
However, can someone tell the correct way how to this things, I this it must be done in Module initialization section.
MatthiasG shows the way to define modules in MEF. Note that the view itself does not implement IModule. However, the interesting part of using MEF with PRISM is how to import the modules into your UI at startup.
I can only explain the system in principle here, but it might point you in the right direction. There are always numerous approaches to everything, but this is what I understood to be best practice and what I have made very good experiences with:
Bootstrapping
As with Prism and Unity, it all starts with the Bootstrapper, which is derived from MefBootstrapper in Microsoft.Practices.Prism.MefExtensions. The bootstrapper sets up the MEF container and thus imports all types, including services, views, ViewModels and models.
Exporting Views (modules)
This is the part MatthiasG is referring to. My practice is the following structure for the GUI modules:
The model exports itself as its concrete type (can be an interface too, see MatthiasG), using [Export(typeof(MyModel)] attribute. Mark with [PartCreationPolicy(CreationPolicy.Shared)] to indicate, that only one instance is created (singleton behavior).
The ViewModel exports itself as its concrete type just like the model and imports the Model via constructor injection:
[ImportingConstructor]
public class MyViewModel(MyModel model)
{
_model = model;
}
The View imports the ViewModel via constructor injection, the same way the ViewModel imports the Model
And now, this is important: The View exports itself with a specific attribute, which is derived from the 'standard' [Export] attribute. Here is an example:
[ViewExport(RegionName = RegionNames.DataStorageRegion)]
public partial class DataStorageView
{
[ImportingConstructor]
public DataStorageView(DataStorageViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
The [ViewExport] attribute
The [ViewExport] attribute does two things: Because it derives from [Export] attribute, it tells the MEF container to import the View. As what? This is hidden in it's defintion: The constructor signature looks like this:
public ViewExportAttribute() : base(typeof(UserControl)) {}
By calling the constructor of [Export] with type of UserControl, every view gets registered as UserControl in the MEF container.
Secondly, it defines a property RegionName which will later be used to decide in which Region of your Shell UI the view should be plugged. The RegionName property is the only member of the interface IViewRegionRegistration. The attribute class:
/// <summary>
/// Marks a UserControl for exporting it to a region with a specified name
/// </summary>
[Export(typeof(IViewRegionRegistration))]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
public ViewExportAttribute() : base(typeof(UserControl)) {}
/// <summary>
/// Name of the region to export the View to
/// </summary>
public string RegionName { get; set; }
}
Importing the Views
Now, the last crucial part of the system is a behavior, which you attach to the regions of your shell: AutoPopulateExportedViews behavior. This imports all of your module from the MEF container with this line:
[ImportMany]
private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews;
This imports all types registered as UserControl from the container, if they have a metadata attribute, which implements IViewRegionRegistration. Because your [ViewExport] attribute does, this means that you import every type marked with [ViewExport(...)].
The last step is to plug the Views into the regions, which the bahvior does in it's OnAttach() property:
/// <summary>
/// A behavior to add Views to specified regions, if the View has been exported (MEF) and provides metadata
/// of the type IViewRegionRegistration.
/// </summary>
[Export(typeof(AutoPopulateExportedViewsBehavior))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class AutoPopulateExportedViewsBehavior : RegionBehavior, IPartImportsSatisfiedNotification
{
protected override void OnAttach()
{
AddRegisteredViews();
}
public void OnImportsSatisfied()
{
AddRegisteredViews();
}
/// <summary>
/// Add View to region if requirements are met
/// </summary>
private void AddRegisteredViews()
{
if (Region == null) return;
foreach (var view in _registeredViews
.Where(v => v.Metadata.RegionName == Region.Name)
.Select(v => v.Value)
.Where(v => !Region.Views.Contains(v)))
Region.Add(view);
}
[ImportMany()]
private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews;
}
Notice .Where(v => v.Metadata.RegionName == Region.Name). This uses the RegionName property of the attribute to get only those Views that are exported for the specific region, you are attaching the behavior to.
The behavior gets attached to the regions of your shell in the bootstrapper:
protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
ViewModelInjectionBehavior.RegionsToAttachTo.Add(RegionNames.ElementViewRegion);
var behaviorFactory = base.ConfigureDefaultRegionBehaviors();
behaviorFactory.AddIfMissing("AutoPopulateExportedViewsBehavior", typeof(AutoPopulateExportedViewsBehavior));
}
We've come full circle, I hope, this gets you an idea of how the things fall into place with MEF and PRISM.
And, if you're still not bored: This is perfect:
Mike Taulty's screencast
The way you implemented HelloView means that the View has to know the exact implementation of IHelloViewModel which is in some scenarios fine, but means that you wouldn't need this interface.
For the examples I provide I'm using property injection, but constructor injection would also be fine.
If you want to use the interface you can implement it like this:
[Export(typeof(IHelloView)]
public partial class HelloView : UserControl, IHelloView
{
public HelloView()
{
InitializeComponent();
}
[Import]
public IHelloViewModel Model
{
get { return DataContext as IHelloViewModel; }
set { DataContext = value; }
}
}
[Export(typeof(IHelloViewModel))]
public class HelloViewModel : IHelloViewModel
{
}
Otherwise it would look like this:
[Export(typeof(IHelloView)]
public partial class HelloView : UserControl, IHelloView
{
public HelloView()
{
InitializeComponent();
}
[Import]
public HelloViewModel Model
{
get { return DataContext as HelloViewModel; }
set { DataContext = value; }
}
}
[Export]
public class HelloViewModel
{
}
One more thing: If you don't want to change your Views or provide several implementations of them, you don't need an interface for them.
I have the following context:
public class DataContext : DbContext
{
/// <summary>
/// Gets or sets Addresses.
/// </summary>
public DbSet<Address> Addresses { get; set; }
/// <summary>
/// Gets or sets Users.
/// </summary>
public DbSet<Users> Users { get; set; }
}
I my application user may change data in say user data and then he may want to cancel changes. The best way to do this, is to refresh the DataContext from the database. But DbContext has no Refresh method. How can I refresh my DataContext?
You can reload the entity from the database as follows.
context.Entry(user).Reload();
Or you can try out the methods described in this question.
Problem - user clicks "do something" button (view), view model receives command and passes it to model (function call). Some time passes and model is done processing data (async). How does model notifies viewmodel about "need update"/"done"?
What is the best aproach? How can i seperate Model from ViewModel in this scenario?
You could implement a plain old event in your Model which can be subscribed to from the ViewModel.
Update
In response to your comment.
If you are using multiple threads, then you will need to know about the "Dispatcher" framework to ensure that calls from non-UI threads are properly synchronized onto the UI thread. This is a requirement of WPF. Please see:
http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
I think the normal approach for doing this is to use the INotifyPropertyChanged interface. I'm not 100% certain how it works as I'm still fairly new to WPF, but normally you fire an event whenever a property changed, passing in the name of the property and that updates the binding for that property.
Below's some sample code. You'd then be binding to the IsSelected property (as I believe this should be your ViewModel).
public class TestProperty : INotifyPropertyChanged
{
public Boolean IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
this.NotifyPropertyChanged("IsSelected");
}
}
private bool isSelected;
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notifies the property changed.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
private void NotifyPropertyChanged(String propertyName)
{
this.VerifyPropertyName(propertyName);
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You might find the sample applications of the WPF Application Framework (WAF) helpful. They show how the model can communicate with the ViewModel or the View via events.