I am working on web app in ASP.NET MVC using Entity Framework. It is a Ticket Log tool for chats. So, if a chat comes in Agent will copy email, and Chat Date and Start time, click on SUBMIT. This will simply create an entry for chat in tool with following fields:
Email, ChatStartDateTime, ChatCreatedDateTime
So ChatStartDateTime will be different then ChatCreatedDateTime.
Now the Agent shares support on Chat, and may be he ends the chat after 10 mins. Now, he comes back to the web app and adds his comments for the action taken for chat on web app and clicks a button CHATCOMPLETE.
Clicking this button will update the other field properties like Description field and ChatEndDateTime.
So, now how can I get to know duration in between these fields
ChatStartDateTime and ChatStartDateTime
ChatStartDateTime and ChatEndDateTime
Chat model class:
public class Chat
{
[Key]
public int ChatId { get; set; }
[Required]
public string CustName { get; set; }
public string Query { get; set; }
public string Resolution { get; set; }
[Required]
public DateTime ChatStartDateTime { get; set; }
public DateTime? ChatCreateDateTime { get; set; }
public DateTime? ChatEndDateTime { get; set; }
public int Id { get; set; }
public string Username { get; set; }
public string FirstName { get; set; }
public string Email { get; set; }
[ForeignKey("Id")]
public virtual User User { get; set; }
}
ChatLog controller action
public ActionResult MyChats()
{
using (Db db = new Db())
{
Chat dto = new Chat();
var uName = User.Identity.Name;
ViewBag.myTodayTicket = db.Chats.Where(x => System.Data.Entity.DbFunctions.TruncateTime(x.ChatCreateDateTime) == DateTime.Today && x.Username == uName).Count();
return View(db.Chats.Where(x => x.Username == uName).ToArray().ToList());
}
}
Help is much appreciated.
Here is how I got it resolved #(string.Format("{0:hh\:mm\:ss}", item.ChatEndDateTime-item.ChatCreateDateTime)). Now Checking how can I tally all and get average for all Chat Logs
Related
I have a table in my EF model that is not creating within the database on access.
The table name is "sites" and is linked to a parent table by the use of a foreign key called "CompanyId".
I am attmempting to list all the sites that belong to a specific company (the company table is linked to the ApplicationUser)
I would expect that when i call the database for a list of the sites that it will be created. However i just receive an error that states the table does not exist
My model for the two tables is as follow
public class Company
{
[Key]
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string PostCode { get; set; }
public string County { get; set; }
public string Country { get; set; }
public string TelephoneNumber { get; set; }
public string Email { get; set; }
public virtual IQueryable<Site> Sites { get; set; }
}
public class Site
{
[Key]
public int SiteId { get; set; }
public int CompanyId { get; set; }
public string SiteName { get; set; }
public string Url { get; set; }
}
and my controller
public ActionResult Index()
{
//get the user details
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var currentuser = manager.FindById(User.Identity.GetUserId());
// search
var company = currentuser.Companies;
var sites = company.Sites;
if (sites == null)
{
sites = db.Sites.Where(c => c.CompanyId == company.CompanyId);
return View(sites.ToList());
}
return View(company.Sites.ToList());
}
You can see which table is created in your database using Database Manager?
Try
1: Change
public virtual IQueryable<Site> Sites { get; set; }
for
public virtual ICollection<Site> Sites { get; set; }
2: Add property to your site class
public Company Company { get; set; }
Did you create a migration for the change? If not the issue the "Add-Migration whateverYouWant" command in your package manager console.
Do you have automatic migrations enabled? If not then you have to auth the command "update-database" in your package manager console.
Look into your Configuration.cs file under the Migrations folder
and check the Configuration constructor. There should be a property called "AutomaticMigrationsEnabled" set to true in order for this to do what you are expecting.
I am currently working on a simple comments system.
I have a table that should store comments by following model:
public class Comments
{
[Key]
public int Id { get; set; }
[DataType(DataType.MultilineText)]
public string Text { get; set; }
public DateTime DateCreated { get; set; }
public int FromUserId { get; set; }
public int ToUserId { get; set; }
}
Comments are being written from one user to another on his UserPage.
I get userId from db, looking for id that corresponds my User.Identity.Name (name of authorized user) and pass it to FromUserId.
The question is How can I track on whoose page user is writing comment, in order to pass this to ToUserId.
UserPage is being created dynamically from db.
In MVC i want to authenticate users,they must not be able to see other user data when logged on. Users must be able to CRUD their own data only. I have created two model:
public class User
{
public int id { get; set; }
public string Username { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
public int productId { get; set; }
public string productName { get; set; }
public double productPrice { get; set; }
public User Users { get; set; }
}
And i have product controller, where i want to authenticate users from CRUD other users data.
You can make your code to perform CRUD operations on only the products available for logged in user.
Use below scenario for your requirement.
public class User
{
public int id { get; set; }
public string Username { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public List<Product> Products {
get{
//get all products from database/storage for this user. for ex: I have called a method to get products
//you can filter products related to this user by sending this user id to database or using code like below
//Writing this code/logic in controller would be preferable
return GetAllProducts().Where(p => p.Users.id == this.id).ToList();
}
set;
}
}
Agree with Rajesh, I would recommend you use Current User's data and filter Rajesh you showed. Current User's Data may include Id of current logged user. If you use cookies to keep user's session, you can retrieve his Id from cookies in controller or filter attribute: HttpContext.Current.Request.Cookies["auth_cookie"].
I'm working on a reply from email feature in my app, and I'm using mandrillapp.com. How it works now :
1. User replies from their email to something#something.com
2. Mandril receives the mail and sends the POST request to preconfigured endpoint of my service
3. I process that post request (create internal app message)
With regards to step 3, I have basically code that should create internal app message wrapped in the begin/rescue. So any potential errors would get reported to me, which they have in the past.
However now I've encountered a user who claims that the email has been sent (step 1), I contacted the mandrill support they say they have processed it and send to my endpoint (step 2).
So that only leaves me to see what happened in the step 3, within that specific time range. My app is on heroku, and my logs stored on AWS I could go back in past to that specific time and I could see a successful POST request from mandrill side.
What can I do to catch this case moving forward? And fix it of course, because I have no idea what is going on now.
I was thinking create a model named Mandrill hooks, which would have params column which would be a serialized hash and it would save all the params which came to my endpoint from mandrill.
Then I could check counts of webhooks received by my account and the ones sent by mandrill, and hopefully I spot 1 with different count, and since I will have the params data in my db, I'd be able to reproduce the case.
Or is there more wise approach, as this looks naive even to me?
I think there may be a wiser approach that enables you to have more control over everything and this sounds extremely similar to what I recently accomplished and I answered a similar question here. Does this help at all or is there some more specific help that you would like?
** Edit: Linked post/code below
I am running my Mandrill Webhook handling as an API project in VS and this is how I am have gotten it up and running:
[HttpPost]
public string Post()
{
/* Every Mandrill webhook uses the same general data format, regardless of the event type.
* The webhook request is a standard POST request with a single parameter (currently) - 'mandrill_events'. */
string validJson = HttpContext.Current.Request.Form["mandrill_events"].Replace("mandrill_events=", ""); //"mandrill_events=" is not valid JSON. If you take that out you should be able to parse it. //http://stackoverflow.com/questions/24521326/deserializing-mandrillapp-webhook-response
List<MandrillEvent> mandrillEventList = JsonConvert.DeserializeObject<List<MandrillEvent>>(validJson);
foreach (MandrillEvent mandrillEvent in mandrillEventList)
{
if (mandrillEvent.msg.email != null)
{
DataLayer.ReportingData.EmailSave(mandrillEvent); //Saves MandrillEvent email to database and sets a messageId for datalayer
}
}
foreach (MandrillEvent mandrillEvent in mandrillEventList)
{
DataLayer.ReportingData.MandrillEventSave(mandrillEvent); //Saves MandrillEvent object to database
}
return "DONE";
}
I then took the documented (and undocumented) JSON parameters of "mandrill_event" and used json2csharp.com to generate the C# properties. I created a class called "MandrillEvent.cs" and put these within:
public class SmtpEvent
{
public int ts { get; set; }
public DateTime SmtpTs { get; set; }
public string type { get; set; }
public string diag { get; set; }
public string source_ip { get; set; }
public string destination_ip { get; set; }
public int size { get; set; }
public int smtpId { get; set; } //added for datalayer
}
public class Msg
{
public int ts { get; set; }
public DateTime MsgTs { get; set; }
public string _id { get; set; }
public string state { get; set; }
public string subject { get; set; }
public string email { get; set; }
public List<object> tags { get; set; }
public List<object> opens { get; set; } //an array of containing an item for each time the message was opened. Each open includes the following keys: "ts", "ip", "location", "ua"
public List<object> clicks { get; set; } //an array containing an item for each click recorded for the message. Each item contains the following: "ts", "url"
public List<SmtpEvent> smtp_events { get; set; }
public List<object> resends { get; set; } //not currently documented on http://help.mandrill.com/entries/58303976-Message-Event-Webhook-format
public string _version { get; set; }
public string diag { get; set; } //for bounced and soft-bounced messages, provides the specific SMTP response code and bounce description, if any, received from the remote server
public int bgtools_code { get; set; } //Is it this? for bounced and soft-bounced messages, a short description of the bounce reason such as bad_mailbox or invalid_domain. (not currently documented but in JSON response)
public string sender { get; set; }
public object template { get; set; }
public string bounce_description { get; set; }
public Msg()
{
tags = new List<object>();
opens = new List<object>();
clicks = new List<object>();
smtp_events = new List<SmtpEvent>();
smtp_events.Add(new SmtpEvent());
resends = new List<object>();
}
}
public class MandrillEvent
{
public string #event { get; set; }
public string _id { get; set; }
public Msg msg { get; set; }
public int ts { get; set; }
public DateTime MandrillEventTs { get; set; }
public int messageId { get; set; } //added for datalayer
public List<string> SingleMandrillEventData { get; set; } //added for Reporting
public MandrillEvent()
{
SingleMandrillEventData = new List<string>();
msg = new Msg();
}
}
You now have your "mandrill_events" JSON object as a functioning C# object!! Did this help or do you need some more clarification/help?
I'm using ASP.Net MVC 5 from Visual Studio. I want to create a user profile with complex types. I have modified the code of the User class in IdentityModels.cs file. Here's the code:
public class User : IUser
{
public User()
: this(String.Empty)
{
}
public User(string userName)
{
UserName = userName;
Id = Guid.NewGuid().ToString();
}
[Key]
public string Id { get; set; }
public string UserName { get; set; }
public string Phone { get; set; }
public string MobilePhone { get; set; }
public string Email { get; set; }
public string Address { get; set; }
}
I've also changed the views for this model. This works great without any problems. However, if I change the type of the Address property above to Address, meaning: public Address Address { get; set; } it fails.
I've tried using the virtual keyword for it but it didn't work. Please note that every time I create the database tables from scratch. Also, I checked the database and the information is inserted into database with correct foreign keys but I don't know what the problem is.
The code execution fails in the code below in the line await Users.Create(user) which returns false:
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Create a profile, password, and link the local login before signing in the user
User user = new User(model.UserName)
{
UserAddress = model.Address,
Email = model.Email,
Phone = model.Phone,
MobilePhone = model.MobilePhone
};
if (await Users.Create(user) &&
await Secrets.Create(new UserSecret(model.UserName, model.Password)) &&
await Logins.Add(new UserLogin(user.Id, IdentityConfig.LocalLoginProvider, model.UserName)))
{
await SignIn(user.Id, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError(String.Empty, "Failed to create login for: " + model.UserName);
}
}
catch (DbEntityValidationException e)
{
ModelState.AddModelError("", e.EntityValidationErrors.First().ValidationErrors.First().ErrorMessage);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Update:
Here's the Address class in case you wonder:
public class Address
{
public int ID { get; set; }
[Required]
public string Country { get; set; }
[Required]
public string City { get; set; }
[Required]
public string Street { get; set; }
[Required]
public string PostalCode { get; set; }
}
Update 2
Here's the image of the entered data:
It seems that this is a bug. I won't select this as the answer until it is absolutely proven. However when I change my controller's code from:
if (await Users.Create(user) &&
await Secrets.Create...
to:
await Users.Create(user);
if (await Secrets.Create...
it works without any problems. Seems to me that this should be a bug since I can load and edit the data perfectly.
This means that for some reason, even if the IUserStore.Create succeeds, it returns false in case the model is a complex type.
The problem that you have here (at least specific to changing Address to be an object rather than a string), is that your models aren't built correctly to relate them properly. Here is what you should be looking at.
public class User : IUser
{
public User()
: this(String.Empty)
{
}
public User(string userName)
{
UserName = userName;
Id = Guid.NewGuid().ToString();
}
[Key]
public string Id { get; set; }
public string UserName { get; set; }
public string Phone { get; set; }
public string MobilePhone { get; set; }
public string Email { get; set; }
// This FK doesn't need to explicitly be declared, but I do so as it helps me
// with the understanding of my structure a bit better.
public int AddressId { get; set; }
public Address Address { get; set; }
}
You also need to relate your Address back to your User class. I'm not sure how you want to do that, but, assuming that multiple people can live at the same address, you'll want a one-to-many relationship. (Right now, you receive an error because you don't specify the relationship.)
You have to do this in the Address model:
public class Address
{
[Key]
public int ID { get; set; }
[Required]
public string Country { get; set; }
[Required]
public string City { get; set; }
[Required]
public string Street { get; set; }
[Required]
public string PostalCode { get; set; }
// I would give this a better property name than "Users" but just putting
// this here for now.
public virtual ICollection<User> Users { get; set; }
}
This way, when your database builds, Entity Framework can now properly build the relationships (where, before, it couldn't tell what you intended - hence the error when you switch over to Address).
Of course, there may be other issues, but, this is one that would cause problems.