MVVM Light Messaging Issue - mvvm-light

I am facing with series of issues while using MVVMLight.
One of them is passing non-string messages across the application.
This is the message type I am passing -
public class NameValue
{
public NameValue()
{
}
public string Name { get; set; }
public string Value { get; set; }
}
in the View1
Messenger.Default.Send<NameValue>(nv, "Message1");
in the ViewModel2
Messenger.Default.Register<NameValue>(this, "Message1", OnMessageSent);
private void OnMessageSent(NameValue nv)
{
}
When I pass a message using Messender.Default from a View to another ViewModel it works when the message type is string but not when message type is 'NameValue'.
Please let me know if someone else is facing the same problem or there is some thing wrong in the implementation.

I was able to resolve this issue by debugging the SL4 source code uploaded on Friday.
The issue was in the code where the message was being registered for listening different 'type' of messages with same name.

Related

EF Core with CosmosDB: OwnsOne and OwnsMany throw NullReferenceException

I'm working on a new project that uses CosmosDB and Entity Framework Core (via the Microsoft.EntityFrameworkCore.Cosmos NuGet package, version 5.0.7; the project itself is .NET Core 5). I'm new to both, and running into an issue I can't sort out.
In short, I need to save a complex object to the database. It's a big model that will have multiple collections of classes underneath it, each with their own properties and some with collections underneath them as well. I'm trying to configure EF with OwnsOne and OwnsMany to store these child objects underneath the top-level one. The code compiles, and will save to the database so long as all the owned objects are left empty. But whenever I put anything into an owned object, either with OwnsOne or OwnsMany, I get a pair of NullReferenceExceptions.
I've tried to strip my code down to the very basics. Here's how it currently looks.
Owner and owned classes:
public class Questionnaire
{
// Constructors
private Questionnaire() { }
public Questionnaire(Guid id)
{
Test = "Test property.";
TV = new TestQ();
Id = id;
}
public Guid Id { get; set; }
public string Test { get; set; }
public TestQ TV { get; set; }
// Public Methods
public void AddForm(Form f)
{
// not currently using this method
//Forms.Add(f);
}
}
public class TestQ
{
public TestQ()
{
TestValue = "test ownsone value";
}
public string TestValue { get; set; }
}
DbContext:
public class QuestionnaireDbContext : DbContext
{
public DbSet<Questionnaire> Questionnaires { get; set; }
public QuestionnaireDbContext(DbContextOptions<QuestionnaireDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultContainer(nameof(Questionnaires));
modelBuilder.Entity<Questionnaire>().HasKey(q => q.Id);
modelBuilder.Entity<Questionnaire>().OwnsOne(q => q.TV);
}
}
And the code from the service that calls the dbContext (note that this is based on a generic service that I didn't set up originally). The actual exceptions are thrown here.
public virtual TEntity Add(TEntity entity)
{
_context.Entry(entity).State = EntityState.Added;
_context.SaveChanges();
return entity;
}
Ultimately I need this to work with OwnsMany and a collection, but I figured it might be simpler to get it working with OwnsOne first. The key thing to note here is that if I comment out the line
TV = new TestQ();
in the Questionnaire class, the model persists correctly into CosmosDB. It's only when I actually instantiate an owned entity that I get the NullReferenceExceptions.
Any advice would be much appreciated! Thank you!
Well, I'm not sure why this is the case, but the issue turned out to be with how we were adding the document. Using this generic code:
public virtual async Task<TEntity> Add(TEntity entity)
{
_context.Entry(entity).State = EntityState.Added;
await _context.SaveChanges();
return entity;
}
was the issue. It works just fine if I use the actual QuestionnaireDbContext class like so:
context.Add(questionnaire);
await context.SaveChangesAsync();

Using Backlink feature of realm-dotnet in Xamarin.Forms App

My current employer is developing a mobile app using Xamarin.Forms and Asp.net mvc on the backend. I suggested to use realm in the mobile app. My manager want to see a POC(Proof of concept) app using realm with backlink feature before allowing it to be used in the app. I am working on the POC on GitHub . The documentation is very limiting and the GitHub repo of realm-dotnet don’t have good sample.
I completed the project. But unable to implement backlink. The sample app I have developed allow user to create assignees(employees) in the first page. The user can delete or edit the employees using context menu. When the user clicks on the employee name the app navigates to the ToDoListPage of that particular employee. Here the user can create ToDoItems. On this ToDoList page I want to show the ToDoItems that where assigned to that employee only.
The models were as follows:
public class Assignee : RealmObject
{
public Assignee()
{
ToDoItems = Enumerable.Empty<ToDoItem>().AsQueryable();
}
[PrimaryKey]
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Name { get; set; }
public string Role { get; set; }
[Backlink(nameof(ToDoItem.Employee))]
public IQueryable<ToDoItem> ToDoItems { get; }
}
public class ToDoItem : RealmObject
{
[PrimaryKey]
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Name { get; set; }
public string Description { get; set; }
public bool Done { get; set; }
public Assignee Employee { get; set; }
}
I am adding employee to each ToDo Item:
Item.Employee = Employee;
_realm.Add(Item);
Now I want to access the ToDoItems for the Employee:
Items = _realm.All<Assignee>().Where(x => x.Id == EmployeeId).FirstOrDefault().ToDoItems;
But this does not work. I will be grateful if someone can help me out by preferably writing code in my sample app or write the correct code in the reply.
Thank you
Firstly, Realm .NET doesn't currently support traversing properties (x.Employee.Id). Due to this, when I start the app and try to go to the ToDoListPage, the app crashes with the exception:
The left-hand side of the Equal operator must be a direct access to a persisted property in Realm
Realm supports object comparison, so we can fix this like so:
var employee = _realm.Find<Assignee>(EmployeeId);
Items = _realm.All<ToDoItem>().Where(x => x.Employee == employee);
Secondly, everything seemed fine in your code, so I dug a bit deeper and saw why it isn't working. The issue is that when we try to get all items with the code above, the EmployeeId parameter is null. Since the EmployeeId is being populated after the load logic has been triggered, we don't need to load the data in the ctor. So you can remove this code.
Finally, since you won't be loading the data in the ctor, and instead in the SetValues method, the UI needs to know, when the data has been updated, what exactly to redraw. Thus, you need to mark the collection to be Reactive too:
[Reactive]
public IEnumerable<ToDoItem> Items { get; set; }
Then, you need to change the SetValues method to use object comparison, instead of traversing:
async Task SetValues()
{
Employee = _realm.Find<Assignee>(EmployeeId);
Title = Employee.Name;
Items = _realm.All<ToDoItem>().Where(x => x.Employee == Employee);
}
To sum up - you don't need to try and load the data in the ctor, since you don't know when the EmployeeId will be set. You are already tracking when the property will change and inside the SetValues command you simply need to change the expression predicate.

I could not connect to database instance created with Entity Framework generated from model

I created a web application and a model. Then I generated a dbcontext class and a database instance. After I built the project, I tried to connect to that database from Server Explorer in Visual Studio, but could not connect.
I tried to test connection but got an error:
This connection cannot be tested because the specified database does not exist or is not visible to the specified user
Whenever I tried to scaffold view or controller I got this error:
Unable to retrieve metadata for ... one or more validation errors were detected during model generation
ModelsTable is based on type TestModel that has no keys defined.
When I created database object in controller class and write query got same error no key defined.
Also made updates on packages and tried again. I think my connection string is correct.
Here is my model.
public class TestModel
{
[Key]
public string ID { get; } = Guid.NewGuid().ToString();
public string AreaName { get; set; }
public bool IsWorking { get; set; }
public string UserName { get; set; }
public DateTimeOffset Time { get; set; }
}
So I could not use scaffolding, Entity Framework and write query.
Here is my dbcontext class.
public class ModelDB : DbContext
{
public ModelDB()
: base("name=ModelDB")
{
}
public DbSet<TestModel> ModelsTable { get; set; }
}
I searched on internet tried founded solutions but did not understand and could not solve. I hope did not ask unnecessary questions. Thanks for your helping.
Are you using Code First? If so I think you need to generate migrations.
In visual studio go to Package Manager Console and run this commands:
Add-Migration "modelClassName"
Update-Database –Verbose
For more information refer to this link: https://msdn.microsoft.com/en-us/library/jj591621(v=vs.113).aspx
You are missing the set; in the field ID.

How to decouple MediatR from my business layer

Good morning.
I'm using domain events in my project, and the easiest way i found to implement it was by using MediatR.
But i don't want my project to directly depend on it, i want apply dependency inversion to hide the library.
Current code that has a dependency in Mediator, because of INotification interface
public class EmailConfirmedEvent : INotification
{
public Guid PassengerId { get; }
public string Email { get; }
public EmailConfirmedEvent(Guid passengerId, string email)
{
Email = email;
PassengerId = passengerId;
}
}
But i want to be like this:
public class EmailConfirmedEvent : IMyProjectDomainEvent
{
public Guid PassengerId { get; }
public string Email { get; }
public EmailConfirmedEvent(Guid passengerId, string email)
{
Email = email;
PassengerId = passengerId;
}
}
By some way i'll need to "convert" from mediator events/event handlers to my project events/event handlers.
What's the best way to do this.
Thanks in advance.
I ended up creating my domain event custom code using StructureMap and reflection to resolve the event handlers at runtime.
Code sample here: https://github.com/Henry-Keys/domain-events-sample
I generally make base classes that inherit from MediatR interfaces/base. Then if you change libraries (unlikely) you just have to update the base classes and the rest of the implement remains untouched.

Update User Details in MVC5

I am trying to update user details.
Here is my code.
My Model-
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
public string MobileNumber { get; set; }
public string Email { get; set; }
}
The Controller-
[HttpPost]
public ActionResult UpdateUser(ApplicationUser UserProfile)
{
if (ModelState.IsValid)
{
var result = UserManager.Update(UserProfile);
if (result.Succeeded)
return View(UserProfile);
else
{
return View(UserProfile);
}
}
return View(UserProfile);
}
"result.Error.strings" gets the value
Name suresh already taken
Based upon the the error message, i'm guessing your Database already has the user with name Suresh
Try another name if the error still exists update your question and my be you can get more help.
The other way you could update an user could be first find the user then update the required fields then update(save) user.
I had the same problem. figured out that when one does not set the ID of the user that needs to be updated, the EF context undercover treats the user object as the new entity.
fixing the error with the ID, I've got a new error, so to help anyone struggling (and to scip a couple of steps) - I pointing to an answer that explains it:
asp.net identity 2.0 update user

Resources