Join 2 services and use on Controller on ASP.NET Core - database

I have a view Model:
public class CountViewModel
{
public int NewsLetterEmailCount { get; set; }
public int CurrentMonthNewsLetter { get; set; }
public int NewsLetterPercentage { get; set; }
}
then I create the second ViewModel that want to list of title:
public class AdminDashboardUnreadMessage
{
[Display(Name = "عنوان")]
public string Title { get; set; }
//public List<AdminDashboardUnreadMessage>
AdminDashboardUnreadMessages { get; set; }
}
I have a ticket Table, these are my 2 services:
public async Task<CountViewModel> AdminContentCount()
{
CountViewModel adminContetnCount = new CountViewModel()
{
UserCount = await _userRepository.UserCount(),
CurrentMonthUser = await _userRepository.CurrentMonthUser(),
NewsLetterEmailCount = await _newsLetterRepository.NewsLetterEmailCount(),
CurrentMonthNewsLetter = await _newsLetterRepository.CurrentMonthNewsLetterEmail(),
return adminContetnCount;
}
public async Task<List<AdminDashboardUnreadMessage>> ShowUnReadTicketMessages()
{
return await _userRepository.ShowUnReadTicketMessages();
}
How can I use 2 services on my service
I mean I don't want to use from View Data

I think you need to define a new ViewModel like this :
public class NewViewModel
{
public CountViewModel CountModel { get; set; }
public AdminDashboardUnreadMessage AdminDashboardModel { get; set; }
}
And now you need to return this object as a result of a newly created service which responsible to aggregate the result of two different services.
public async Task<NewViewModel> NewService()
{
var adminContetnCount = await AdminContentCount();
var dashboard = await ShowUnReadTicketMessages();
return new NewViewModel
{
CountModel = adminContetnCount,
AdminDashboardModel= dashboard
};
}

Related

update and delete (single query) (EF + .NET Core Api)

what's up? I have an API made with .NET Core API + EF where I have a Many-to-Many relationship between Doctor and Specialty, from which a DoctorSpecialities table arises. That is, a doctor can have several specialties.
I use React JS and what I want to do is have in the interface, a table with the specialties of the chosen doctor and when I send the form, the data in the DoctorSpecialities table is updated or deleted.
If the user deleted or added specialties, can all that be done in a single query?
My question is how to do the controller method, with that I have problems.
Doctor
public partial class Doctor
{
public Doctor()
{
DoctorSpecialties = new HashSet<DoctorSpecialties>();
}
public int DoctorId { get; set; }
public string DoctorName { get; set; }
public string DoctorProfileImg { get; set; }
public string DoctorPhoneNumber { get; set; }
public string DoctorEmail { get; set; }
public string DoctorStatus { get; set; }
public string DoctorGender { get; set; }
public ICollection<DoctorSpecialties> DoctorSpecialties { get; set; }
}
Specialty
public partial class Specialty
{
public Specialty()
{
DoctorSpecialties = new HashSet<DoctorSpecialties>();
}
public int SpecialtyId { get; set; }
public string SpecialtyName { get; set; }
public ICollection<DoctorSpecialties> DoctorSpecialties { get; set; }
}
DoctorSpecialties
public partial class DoctorSpecialties
{
public DoctorSpecialties()
{
Appointment = new HashSet<Appointment>();
DoctorSchedule = new HashSet<DoctorSchedule>();
}
public int DoctorSpecialtiesId { get; set; }
public int? DoctorId { get; set; }
public int? SpecialtyId { get; set; }
[JsonIgnore]
public Doctor Doctor { get; set; }
public Specialty Specialty { get; set; }
public ICollection<Appointment> Appointment { get; set; }
public ICollection<DoctorSchedule> DoctorSchedule { get; set; }
}
Context
modelBuilder.Entity<DoctorSpecialties>(entity =>
{
entity.ToTable("doctor_specialties");
entity.Property(e => e.DoctorSpecialtiesId).HasColumnName("doctor_specialties_id");
entity.Property(e => e.DoctorId).HasColumnName("doctor_id");
entity.Property(e => e.SpecialtyId).HasColumnName("specialty_id");
entity.HasOne(d => d.Doctor)
.WithMany(p => p.DoctorSpecialties)
.HasForeignKey(d => d.DoctorId)
.HasConstraintName("FK__doctor_sp__docto__2A4B4B5E");
entity.HasOne(d => d.Specialty)
.WithMany(p => p.DoctorSpecialties)
.HasForeignKey(d => d.SpecialtyId)
.HasConstraintName("FK__doctor_sp__speci__29572725");
});
I tried with:
[HttpPut("test/{id}")]
public async Task<IActionResult> Edit(int id, Doctor doctor)
{
if (id != doctor.DoctorId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
Doctor plantToBeUpdated = await _context.Doctor.Include(p => p.DoctorSpecialties).FirstOrDefaultAsync(p => p.DoctorId == id);
if (plantToBeUpdated != null)
{
plantToBeUpdated.DoctorSpecialties.Clear();
if (doctor.DoctorSpecialties.Count > 0)
{
foreach (var scId in doctor.DoctorSpecialties)
{
plantToBeUpdated.DoctorSpecialties.Add(new DoctorSpecialties()
{
DoctorId = plantToBeUpdated.DoctorId,
SpecialtyId = scId.SpecialtyId
});
}
}
plantToBeUpdated.DoctorName = doctor.DoctorName;
_context.Doctor.Update(plantToBeUpdated);
await _context.SaveChangesAsync();
}
}
catch (DbUpdateConcurrencyException)
{
throw;
}
}
return Ok(doctor);
}
but, doesn't work :c

ArgumentNullException: Value cannot be null. (Parameter 'source')

I have parent and childs nested tables.
Here is my model:
public class Categories
{
[Key]
public int CategoriesId { get; set; }
public int Order { get; set; }
public string CategoryName { get; set; }
public List<News> News { get; set; }
}
public class News
{
[Key]
public int NewsId { get; set; }
public int CategoriesId { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
...
public List<Comments> Comments { get; set; }
public Categories Categories { get; set; }
}
public class Comments
{
[Key]
public int CommentsId { get; set; }
public int NewsId { get; set; }
public string Comment { get; set; }
...
public News News { get; set; }
}
public class NewsImages
{
[Key]
public int ImageId { get; set; }
public int NewsId { get; set; }
public string ImageUrl { get; set; }
public bool Cover { get; set;}
...
public News News { get; set; }
}
I'm trying to send it from ViewComponent to View;
public async Task<IViewComponentResult> InvokeAsync()
{
var group = _dbContext.Categories.Where(k => k.Order != 0).OrderBy(h => h.Order)
.Select(c => new
{
C = c,
N = c.News.OrderByDescending(n => n.Date).Take(5)
.Select(r => new
{
Y = r.Comments,
R = r.NewsImages.Where(rs => rs.Cover == true).FirstOrDefault()
})
});
var model = group
.Select(m => m.C);
return View(await model.ToListAsync()) ;
}
I am sure there are enough News records for every Category, But I get error :
ArgumentNullException: Value cannot be null. (Parameter 'source')
AspNetCore.Views_Shared_Components_IndexKategori_Default.ExecuteAsync() in Default.cshtml
var bp = k.News.FirstOrDefault();
if I use that code works fine :
var model = _dbContext.Categories
.Include(h => h.News).ThenInclude(h => h.Comments)
.Include(h => h.News).ThenInclude(h => h.NewsImages)
.Where(h => h.Order != 0)
.OrderBy(h => h.Order)
But when I use the code above, a few records appear for some categories, and some categories react as if there are no records.
Where am I making mistakes?
Thank you in advance for those who helped ..
Whenever you have a big LINQ statement that throws an exception, and you can't find where the exception comes form, translate the LINQ into smaller steps, and ToList() every step.
public async Task<IViewComponentResult> InvokeAsync()
{
// Temp code: small steps, ToList after every step
var a = dbContext.Categories.Where(category => category.Order != 0).ToList();
var b = a.OrderBy(category => category.Order).ToList();
var c = b.Select(category => new
{
Category = category,
News = category.News.OrderByDescending(news => news.Date)
.Take(5)
.ToList();
})
.ToList();
var d = c.Select(item => new
{
Category = item.Category,
NewsItems = item.News.Select(news => new
{
Comments = news.Comments,
Images = news.NewsImages.Where(newsImage => newsImage.Cover).ToList(),
})
.ToList(),
})
.ToList();
var e = d.Select(item => new
{
Category = item.Category,
NewsItems = item.NewsItems.Select(newsItem => new
{
Comments = newsItem.Comments,
Images = images.FirstOrDefault();
})
.ToList(),
})
.ToList();
// original code:
var group = _dbContext.Categories.Where...
}
I'm sure that your debugger will tell you which step is incorrect.

Data received from angularjs to MVC controller is null

Dears, I have two classes Master and detail named by Raterequest and Raterequestdetails. I have created a viewmodel contains both of them.
in Angularjs i have an object contains rate and a list contains orderdetails.
when i debug the controller the data received is null for both
here is the code
Rate request class
public class RateRequests
{
public int RateRequestsID { get; set; }
public DateTime RateRequestsDate { get; set; }
public string RateRequestName { get; set; }
public string RateRequestType { get; set; }
public string RateRequestMode { get; set; }
}
Rate request details class
public class RateRequestsLines
{
public int RateRequestsLinesID { get; set; }
public int RateRequestsID { get; set; }
[ForeignKey("RateRequestsID")]
public virtual RateRequests RateRequestsFK { get; set; }
public short FCLCNTRS { get; set; }
public short FCLCNTRSSIZE { get; set; }
public string FCLCNTRSTYPE { get; set; }
}
Rate request view model
public class RateRequestViewModel
{
public RateRequests rate { get; set; }
public IEnumerable<RateRequestsLines> ratelines { get; set; }
}
Angularjs
var linkers = angular.module("linkers", [])
.service("linkersSrv", function ($http) {
var urlBase = "/LinkersEgypt/";
this.save = function (url, ratee) {
return $http({
method: "POST",
url: urlBase + "/" + url,
data: ratee,
̶a̶s̶y̶n̶c̶:̶ ̶f̶a̶l̶s̶e̶,̶
})
};
})
.controller("linkersCon", function ($scope, linkersSrv) {
$scope.fcl = [];
$scope.addFCL = function () {
$scope.fcl.push({ FCLCNTRS: $scope.ncntrs, FCLCNTRSSIZE: $scope.csize, FCLCNTRSTYPE: $scope.ctype });
console.log($scope.fcl);
}
$scope.save = function () {
var ratee = {
rate: {
RateRequestsDate: $scope.rdate,
RateRequestName: $scope.rname,
RateRequestType: $scope.rtype,
RateRequestMode: $scope.smode
},
RateRequestsLines: $scope.fcl
};
console.log(ratee);
var promisepost = linkersSrv.save("RateRequest/AddAllRate", ratee);
promisepost.then(function () {
toastr.success("Successfully saved");
})
}
})
Rate controller
[HttpPost]
public JsonResult AddAllRate (RateRequestViewModel rate)
{
return new JsonResult();
}
Any help
Thanks in advance

How can I auto-update the int ModifiedBy property on a Entity with UserId in Entity Framework 4 when saving?

I am using Simple Membership and a UserProfile table that maintains UserId and UserName:
public partial class UserProfile
{
public UserProfile()
{
this.webpages_Roles = new List<webpages_Roles>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<webpages_Roles> webpages_Roles { get; set; }
}
With Entity Framework I am running the following which is inside my Context:
public partial class UowContext : DbContext
// code to set up DbSets here ...
public DbSet<Content> Contents { get; set; }
private void ApplyRules()
{
var r1 = new Random();
var r2 = new Random();
foreach (var entry in this.ChangeTracker.Entries()
.Where(
e => e.Entity is IAuditableTable &&
(e.State == EntityState.Added) ||
(e.State == EntityState.Modified)))
{
IAuditableTable e = (IAuditableTable)entry.Entity;
if (entry.State == EntityState.Added)
{
e.CreatedBy = // I want to put the integer value of UserId here
e.CreatedDate = DateTime.Now;
}
e.ModifiedBy = // I want to put the integer value of UserId here
e.ModifiedDate = DateTime.Now;
}
}
Here is the schema showing how user information is stored. Note that I store the integer UserId and not the UserName in the tables:
public abstract class AuditableTable : IAuditableTable
{
public virtual byte[] Version { get; set; }
public int CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public int ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
}
Here's an example of a controller action that I use:
public HttpResponseMessage PostContent(Content content)
{
try
{
_uow.Contents.Add(content);
_uow.Commit();
var response = Request.CreateResponse<Content>(HttpStatusCode.Created, content);
return response;
}
catch (DbUpdateException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
}
}
I then have:
public class UowBase : IUow, IDisposable
{
public UowBase(IRepositoryProvider repositoryProvider)
{
CreateDbContext();
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
public IRepository<Content> Contents { get { return GetStandardRepo<Content>(); } }
and:
public class GenericRepository<T> : IRepository<T> where T : class
{
public GenericRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("An instance of DbContext is required to use this repository", "context");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
public virtual void Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
}
How can I determine the UserId from inside of my Context so I can populate the Id in my tables?
In Code you will have UserName with you through:
HttpContext.Current.User.Identity.Name
you can than query UserProfile table against that Name and get the UserId from there and than assign it to ModifiedBy attribute.
Make sure that you query UserProfile table outside the foreach loop :)

Ria Service: Navigation Property is null

For example I have two entities
Class A
{
public Guid Id {get;set;}
public Guid BId {get;set;}
public B InstanceB {get;set;}
}
Class B
{
public Guid Id {get;set}
}
B is related to A, on my silver light application I am creating a new instance of A, and also a new instance of B. The new instance of B does not exist yet. But I need the instance of B on my service.
Can I do this without Entity or Association with Ria Service?
Edit:
My Class A :
public partial class lSync{
// Metadata classes are not meant to be instantiated.
private lSync() {
}
public string ConflictMessage { get; set; }
public DateTime DateInserted { get; set; }
public Guid vValuesId { get; set; }
public Guid ID { get; set; }
public bool IsConflict { get; set; }
public bool IsReadyToSync { get; set; }
public Guid SyncSet { get; set; }
public vValues vValues { get; set; }
}
My Ria Service:
[Invoke]
public lSync[] SynchvValuesFromClient(lSync[] syncs) {
bool noConflict = true;
foreach (lSync sync in syncs) {
var servervValue = GetvValuesByID(sync.vValuesId).FirstOrDefault();
var queuevValues = sync.vValues; //sync.vValues here is null, but my sync.vValuesId is not
if (servervValue== null) {
InsertvValues(queueValue);
}
else {
if (servervValue.IsServerConflict(queueValue)) {
sync.IsConflict = true;
sync.ConflictMessage = "Conflict";
noConflict = false;
break;
}
if (!servervValue.AreValuesEqual(queueValue)) {
UpdatevValues(queueValue);
}
}
}
if (noConflict) {
this.ObjectContext.SaveChanges();
}
return syncs;
}
public IQueryable<vValues> GetvValuesByID(Guid ID) {
return ObjectContext.vValues.Where(t => t.ID == ID);
}
public void InsertvValues(vValues model) {
model.ServerDate = DateTime.UtcNow;
if ((model.EntityState != EntityState.Detached)) {
this.ObjectContext.ObjectStateManager.ChangeObjectState(model, EntityState.Added);
}
else {
this.ObjectContext.vValues.AddObject(model);
}
}
public void UpdatevValues(vValuesmodel) {
model.ServerDate = DateTime.UtcNow;
this.ObjectContext.vValues.AttachAsModified(model, this.ChangeSet.GetOriginal(model));
}
:(
Edit
The order is wrong of your method :)
Make an instance of the service before creating instances of the Entities.
It should be:
public void SyncToServer() {
ContextService service = new ContextService();
var instanceA = new A();
instanceA.InstanceB = new B();
service.SubmitChanges(); //service.SaveChanges() for LinqToEntities
}
Are you reloading after a submit because only adding the [Include] attribute in the DomainService MetaData won't work. You need to do this in the DomainService for LinqToSql
public A GetA()
{
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<A>(a => a.InstanceB);
this.DataContext.LoadOptions = dlo;
return this.DataContext.APlural.FirstOrDefault( ); //don't know the plural of A.
}
LinqToEntities:
public A GetA()
{
return this.MyEntitiesContext.APlural.Include( "instanceB" ).FirstOrDefault( ); //don't know the plural of A.
}
var a = new A(){
B = new B(); //or (B)selectedItem
}
now a.Id and a.BId is 0 until you SaveChanged and return saved A

Resources