Prsim MVVM Event Aggregator Executes Only First Time Change - prism

I have invoiceView for creating invoices and publish the event for refresh the CustomerView. But When I create invoice very first time all done perfectly. But when I create invoices more than one from invoiceview. Event Aggregator published only once remaining changes not updated in customerview.
Here is some code of invoiceview on submit
Customer = _customerService.CustomerById(CustomerId);
Customer.OpenBalance += _invoice.BalanceDue;
_customerService.UpdatCustomer(Customer);
_eventAggregator.GetEvent<CurrentCustomerEvent>().Publish(Customer);
and Here is the CustomerView subscribing the event:
_eventAggregator.GetEvent<CurrentCustomerEvent>().Subscribe(CurrentCustomer);
Subscriber Update Method:
private void CurrentCustomer(Customer customer)
{
object userType;
IsoStorage.Instance.TryGetValue("UserType", out userType);
if (userType != null)
{
IsAdmin = (string) userType == "Admin";
}
Customer = customer;
CustomerInvoices = new ObservableCollection<Invoice>(_customerService.GetAllInvoices().Where(x => x.CustomerId == CustomerId));
SelectedInvoices = new ObservableCollection<Invoice>();
OverDue = CustomerInvoices.Where(x => x.CustomerId == CustomerId && x.DueDate < DateTime.Now).Sum(x => x.BalanceDue);
}

Related

MVC NEt Core 5.0 - Identity help - Adding Users to database (models)

I'm new to Net Core and studying it at the moment. I am creating a web based app for users to create events and register for these events and and need help.
I have an EventsCoordinator and Member Model which inherit from my User model which inherits from ApplicationUser : IdenityUser. In my Account Register.cshtml, I can create new users and they are added to the database in my User table, however I'd like when they select the AccountType (enum value (EventCoordinator, Member) that they will then be added to the applicable table e.g. EventsCoordinator or Member, however I am having trouble doing this. I added an IF statement but not sure what to add then...
I've yet to add roles as I want to create different levels of authorization based on these account types but that will have to try work on that later.
Any help for this newbie, would be great!
Thanks!
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = new User { UserName = Input.Email, Email = Input.Email, FirstName = Input.FirstName, LastName = Input.LastName, DOB = Input.DOB, Address = Input.Address, AccountType = (Models.AccountType)Input.AccountType };
if (AccountType == AccountType.EventCoordinator)
{
}
else
{
}
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
In your if statement add the the user to the table or assign the user its role (EventCoordinator ir Member).
If EventCoordinator & Member are Roles you add the user with the UserManager.
Like
await userManager.AddToRoleAsync(user,"EventCoordinator ");
If those 2 are not roles and are columns in a table in your DB
You add the users id to the specific column in your DB.
If possible specify where or how do you save the AccountType or want to save it

Copy a note from a task to a case

I have a manually invoked process which is tied to the account entity. This process has a number of steps. One of the first steps is to create a task and assign it to someone. It's expected that this person will add some notes and complete the task.
Further down the process, I have a step to create a service case. After this is created, I want to copy the note(s) from the task above to the newly created service case.
I have created a custom workflow activity to try and accomplish this. I have gotten as far as deploying it and using it within my process without any errors and it does copy content into the notes field of the service case, however it copies the title of the task, not the note content and I can't quite fathom out why.
public class CopyNotes : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//get the notes associated with the source entity
Guid copyFromId = CopyFrom.Get(executionContext).Id;
Guid copyToId = CopyTo.Get(executionContext).Id;
EntityCollection copyFromNotes = RetrieveNotes(service, copyFromId);
if (copyFromNotes.Entities.Any())
{
foreach (Entity e in copyFromNotes.Entities)
{
Entity newNote = new Entity("annotation");
newNote.Attributes["subject"] = e.Attributes["subject"];
newNote.Attributes["notetext"] = e.Attributes["notetext"];
newNote.Attributes["objectid"] = new EntityReference() { Id = copyToId, LogicalName = CopyTo.Get(executionContext).LogicalName };
}
}
}
private EntityCollection RetrieveNotes(IOrganizationService service, Guid relatedObject)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "objectid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(relatedObject.ToString());
ColumnSet columns = new ColumnSet("subject", "notetext");
QueryExpression query = new QueryExpression();
query.ColumnSet = columns;
query.EntityName = "annotation";
query.Criteria.AddCondition(condition);
EntityCollection results = service.RetrieveMultiple(query);
return results;
}
[RequiredArgument]
[ReferenceTarget("task")]
[Input("Copy notes from item")]
public InArgument<EntityReference> CopyFrom { get; set; }
[RequiredArgument]
[ReferenceTarget("incident")]
[Input("Copy notes to item")]
public InArgument<EntityReference> CopyTo { get; set; }
}
I think you need to actually create the newNote after defining it.
foreach (Entity e in copyFromNotes.Entities)
{
Entity newNote = new Entity("annotation");
newNote.Attributes["subject"] = e.Attributes["subject"];
newNote.Attributes["notetext"] = e.Attributes["notetext"];
newNote.Attributes["objectid"] = new EntityReference() { Id = copyToId, LogicalName = CopyTo.Get(executionContext).LogicalName };
service.Create(newNote);
}
Once I did that your code worked just fine creating a new note with both the title and note text.
You could do this with a standard workflow, if Async creation is fast enough.
Andreas

Entity Framework creating null entry in the DB on POST

I've got a simple form that creates Categories with a name and a List of Cars assigned to them.
Everything works fine minus the fact that for each entry in the DB I get a second one before that is null everywhere except for the parent BrandId.
[HttpPost]
public ActionResult AddNewCategory(AddNewCategoryPostViewModel categoryInfo)
{
var brand = _repository.GetBrandById(categoryInfo.BrandId);
if (categoryInfo.Name == null || categoryInfo.Cars == null)
{
if (categoryInfo.Name == null)
{
ModelState.AddModelError("Name", "The name cannot be empty.");
}
if (categoryInfo.Cars == null)
{
ModelState.AddModelError("Cars", "At least one car must be selected.");
}
var cars = _insplib.GetDevCategorysForProject((int)brand.Id);
ViewBag.Cars = cars;
ViewBag.Selectedcars = categoryInfo.Cars;
return View(new Category()
{
Brand = brand
});
}
var category = new Category()
{
DateEntered = DateTime.Now,
IsArchived = false,
Name = categoryInfo.Name,
BrandId = categoryInfo.BrandId
};
_repository.AddOrUpdateCategory(category);
// more code here added to add the cars, but not relevant to this issue.
return RedirectToRoute("Category", new { brand = category.Brand.ShortName, categoryId = category.Id });
}
My repository method is:
public Category AddOrUpdateCategory(Category category)
{
if (category.Id == 0)
_context.AddToCategorys(category);
_context.SaveChanges();
return category;
}
As you can see it's a pretty straight forward POST, yet every time I create a Category, I get two entries:
ID Name DateEntered IsArchived
5 NULL NULL NULL 4
6 NewCategory 10/6/2011 False 4
My trick has been to simply go through the table and remove any Category that has null values in Name. But that's obviously not resolving the actual issue.
As per the comments, It is actually your GET that will be creating the blank record when it passes a new Category() to the view.
Some of the ORM's detect new'd up objects and add them to your context for you. Which helpfully creates confusing issues like this one.

LINQ2SQL Entities - Updating only the fields that have changed

I was hoping there was an easier way to do this in my MVC 3 project. In my database, I have a Customer table that is mapped in my application via LINQ2SQL. There is also a partial customer class where I perform updates, look-up etc - which where I have an update method like this:
public static void Update(Customer customer)
{
if (customer == null)
return;
using(var db = new DataBaseContext)
{
var newCustomer = db.Customers.Where(c => c.customer_id = customer.customer_id).SingleOrDefault();
if(newCustomer == null)
return;
newCustomer.first_nm = customer.first_nm;
// ...
// ... Lot's of fields to update
// ...
newCustomer.phone_num = customer.phone_nm;
db.SubmitChanges();
}
}
What I was hoping to find was a less-cumbersome method to update the fields in newCustomer with the corresponding fields in customer that are different.
Any suggestions? Thanks.
I think you can implement IEqualityComparer:
public class Customer
{
public string first_nm { get; set; }
public int phone_num { get; set; }
}
class CustomerComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer x, Customer y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the customer' properties are equal.
return x.first_nm == y.first_nm && x.phone_num == y.phone_num ;
}
}
and do it as follows:
if (newCustomer != customer)
{
myDbContext.Customers.Attach(customer,true); // true means modified.
}
Or implement ICloneable and set newCustomer to customer.Clone(). then there's no need to attach customer since newCustomer is already attached.
in EF(4.1), I think You just have to attach the entity as modified:
myDbContext.Customers.AttachAsModified(customer, this.ChangeSet.GetOriginal(customer), myContext);
UPDATE:
Well, it seems like L2S needs original values of the entity. In reply to your comment, you have a couple choices: Using a timestamp column, returning a subset of entities, or having the original entity in your hand. In your scenario, you have the original entity already:
// This is your original entity
var newCustomer = db.Customers.Where(c => c.customer_id = customer.customer_id).SingleOrDefault();
So you will most probably can do:
if (customer != newCustomer)
{
myDbContext.Customers.Attach(customer, newCustomer);
}
Note: I'd rename newCustomer to originalCustomer if I were you since it's more related to the entity's state.
The problem with this approach is that you have an extra trip to database to get your original customer (newCustomer in your code). Take a look at here, here and definitely here to see how you can use TimeStamp columns to prevent the extra database trip.

Values on PostBack getting lost

I am using MVC3 and classes generetad from EntityFranmework for saving some data into a Database.
The controller
// Get
public ActionResult Create(Guid StudentID)
{
Semester semester = new Semester();
ViewBag.BranchID = new SelectList(db.Branches, "ID", "Name");
semester.Student = db.Students.Single(s => s.ID == StudentID);
return PartialView(semester);
}
//
// POST: /Semester/Create
[HttpPost]
public ActionResult Create(Semester semester)
{
semester.ID = Guid.NewGuid();
semester.CreatedDate = DateTime.Now;
semester.CreatedBy = "ddf";
db.Semesters.AddObject(semester);
db.SaveChanges();
return RedirectToAction("Index", "Student");
}
I do get all the result of the student at get Method but all the student data are Lost at the post method.
Help!
The object passed to POST action is not the same as object passed to the view in GET action. In your POST action you get Semester instance created by MVC using only parameters Request (query string, post data) - that means Student instance is long gone. You will need to pass student ID to POST action and fill it there.
[HttpPost]
public ActionResult Create(Guid studentID, Semester semester)
{
semester.ID = Guid.NewGuid();
semester.CreatedDate = DateTime.Now;
semester.CreatedBy = "ddf";
semester.Student = db.Students.Single(s => s.ID == StudentID);
db.Semesters.AddObject(semester);
db.SaveChanges();
return RedirectToAction("Index", "Student");
}

Resources