I am following this course, and the instructor added code to add records to the DB. The class that's going to be added to the DB looks like this:
public class Gig
{
public int Id { get; set; }
public ApplicationUser Artist { get; set; }
[Required]
public string ArtistId { get; set; }
public DateTime DateTime { get; set; }
[Required]
[StringLength(255)]
public string Venue { get; set; }
public Genre Genre { get; set; }
[Required]
public byte GenreId { get; set; }
}
And there's a view model that's attached to the view, to do the mapping, and it looks like this:
public class GigFormViewModel
{
[Required]
public string Venue { get; set; }
[Required]
[FutureDate]
public string Date { get; set; }
[Required]
[ValidTime]
public string Time { get; set; }
[Required]
public byte Genre { get; set; }
[Required]
public IEnumerable<Genre> Genres { get; set; }
public DateTime GetDateTime() => DateTime.Parse($"{Date} {Time}");
}
I have a create method, that gets form fields, and does the mapping from view model to the model itself, and then tries to add the records to the DB, my create action looks like this:
[Authorize]
[HttpPost]
public ActionResult Create(GigFormViewModel viewModel)
{
viewModel.Genres = _context.Genres.ToList();
if (!ModelState.IsValid)
{
return View(viewModel);
}
var gig = new Gig()
{
GenreId = viewModel.Genre,
ArtistId = User.Identity.GetUserId(),
DateTime = viewModel.GetDateTime(),
Venue = viewModel.Venue
};
_context.Gigs.Add(gig);
_context.SaveChanges();
return RedirectToAction("Index", "Home");
}
On the submit, I get the viewModel's property Genres and populate it with the records from the DB, then I check for ModelState.IsValid. but it's giving me:
Genres Field is required
Although I set it just 2 lines above.
Is there something wrong am doing here? Any guidance is appreciated.
Thanks.
You don't need to add a validation data annotation to Genres property in your view model because it is not a data that is set by users but it is set by you to help your view to get a collection of Genre and populate something like a dropdown list.
Firstly, remove the [Required] attribute that decorates your Genres property in GigFormViewModel.
Secondly, refactor your action method, specially the if bloc like below:
[Authorize]
[HttpPost]
public ActionResult Create(GigFormViewModel viewModel)
{
if (!ModelState.IsValid)
{
// re-populate Genres collection only is tha data is in invalid state.
viewModel.Genres = _context.Genres.ToList();
return View(viewModel);
}
// The remainder code does not change
}
Related
I would like to query a table, which holds workflow events with the appr. user id. And instead of the user id, I would like to show the user name.
I have this model:
public class WorkflowEvent
{
public long Id { get; set; }
public DateTime EventDate { get; set; }
public WorkflowStatus Status { get; set; }
public int UserId { get; set; }
public AppUser User { get; }
public string Note { get; set; }
public long WorkflowId { get; set; }
public long DocumentId { get; set; }
}
And this is the user model (it is the standard IdentityUser, I use Asp.Net Identity):
public class AppUser : IdentityUser<int>
{
public string RealName { get; set; }
public string AppTheme { get; set; }
}
And this is my query:
public IEnumerable<WorkflowEvent> WorkflowEvents(int DocumentId)
{
return DataContext.WorkflowEvents.Where(e => e.DocumentId == DocumentId).Include(e => e.User).OrderBy(e => e.EventDate);
}
Unfortunatelly, I get following error on this: System.InvalidOperationException: Lambda expression used inside Include is not valid. In the WorkflowEvents table, there is a foreign key on the UserId, of course.
Have you any idea, why do I get this error message? What goes wrong?
Both Sami's and Nik's suggestions helped. I added the setter to the AppUser. And then I got the error, that the AppUser object isn't exists. This due to the fact, that I have in my app two datacontexts: one for the domain models and one for Identity. So, I just add this line of code to the domain data context:
public DbSet<AppUser> AspNetUsers { get; set; }
And everything worked like a charm.
Hi I have 2 table name tblGroup and tblSubGroup and tblGroup has GroupId which is primary and tblSubGroup has Groupid which is foreign key.
Below are the model generated for them
tblGroup Model
public partial class tblGroup
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public tblGroup()
{
this.tblSubGroups = new HashSet<tblSubGroup>();
}
public int GroupID { get; set; }
[Required(ErrorMessage = "Group Name is Required")]
public string Title { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<tblSubGroup> tblSubGroups { get; set; }
}
tblSubGroup Model
public partial class tblSubGroup
{
public int SubGroupID { get; set; }
[Display(Name = "tblGroup")]
public int GroupID { get; set; }
[Required(ErrorMessage = "SubGroup Name is Required")]
public string Title { get; set; }
public virtual tblGroup tblGroup { get; set; }
}
Now on deleting record of From GroupTable it is giving issue. Instead I need to validate a message that "This record is bind with another table or entity. So it cannot be deleted". I need to show this kind of message.
As I am new I don't know this things is possible or not
Since you need to verify with the database you move this type of validation to the server.
[HttpPost]
public ActionResult Delete(Group group)
{
var grp = db.Group.FirstOrDefault(g => g.Id == group.Id);
if (HasSubGroups(grp))
{
ModelState.AddError("DeleteValidation", "Cannot delete while sub-groups exists");
return View(group);
}
// delete normally ...
}
Then you could display the errors on the view in several ways. The simplest is just to show the collection.
#Html.ValidationSummary()
I have two models Invoice and Client which has one to many relation. My problem is when I try to create a new invoice the modelstate becomes false because the required fields of the Client object are not filled. I tried to set default values e.g. int property {get; set;} = 1; but this causes to override the property value when I try to retrieve the relational model. I'm new to asp.net any help would be appreciated.
Here is my Client model code:
public class Client
{
public int ClientId { get; set; }//Primary key
[Required]
[Display(Name = "Client/Company Name")]
public string Name { get; set; }
//.....
public List<Invoice> Invoices { get; set; }
}
Invoice Model:
public class Invoice
{
public int InvoiceId { get; set; }//Primary key
[Required]
[Display(Name = "Client/Company Name")]
public int ClientId { get; set; }//Foreign key
public Client client { get; set; }
//....
}
My code to save an invoice:
[HttpPost]//Save quote & redirect to edit quote
public IActionResult Create(Invoice quote)
{
ViewData["Title"] = "Create Quotation";//Set title of the view!
if (ModelState.IsValid)//If quote is validated to true.
{
_context.Invoices.Add(quote);//insert quote
_context.SaveChanges();
//Redirect to edit page to add items to the invoice
return RedirectToAction("Edit", new { id = quote.InvoiceId });
}
//...
}
My code to retrieve invoices with their client names
public IActionResult Index()
{
ViewData["Title"] = "Quotations";//Set title of the view!
//Return with array of all quotations.
return View(_context.Invoices.Include(i => i.client).Where(i => i.isQuote == true).ToArray());
}
Any hints or help would be appreciated.
Found a simpler solution:
Just add virtual keyword and GG
in Invoice Model:
public class Invoice
{
public int InvoiceId { get; set; }//Primary key
[Required]
[Display(Name = "Client/Company Name")]
public int ClientId { get; set; }//Foreign key
public virtual Client client { get; set; }
//....
}
I have a two relational Model first one is
Teacher.cs
public class Teachers
{
[Key]
public int TeacherID { get; set; }
public string TeacherName { get; set; }
public string TeacherLname { get; set; }
public int DepartmentID { get; set; }
public string Image { get; set; }
public Department Department { get; set; }
}
and second is Department.cs
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
public string Image { get; set; }
public List<Teachers> Teachers { get; set; }
When I'm creating a new record, I' choose a Department Name for teacher, and It's adding fine. But When I want to Delete a record there is a error like this
The ViewData item that has the key 'DepartmentID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
Line 32: #Html.DropDownList("DepartmentID", String.Empty)
I don't understand what I need to do. Can you help me?
Thanks a lot
TeacherController
EDIT :
//
// GET: /Teachers/Delete/5
[Authorize(Roles = "A")]
public ActionResult Delete(int id = 0)
{
Teachers teachers = db.Teachers.Find(id);
if (teachers == null)
{
return HttpNotFound();
}
return View(teachers);
}
//
// POST: /Teachers/Delete/5
[Authorize(Roles = "A")]
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Teachers teachers = db.Teachers.Find(id);
db.Teachers.Remove(teachers);
db.SaveChanges();
return RedirectToAction("Index");
}
When you pass an empty string into Html.DropDownList() it looks for a list of items to populate the dropdownlist from the first parameter in the ViewData collection. However, there is already an item in that collection that is of type Int32.
This is one of the many confusing scenarios that happen when you use Html.DropDownList() rather than using a strongly typed model and Html.DropDownListFor()
I suggest you do this:
#Html.DropDownListFor(x => x.DepartmentID, Model.Departments)
You will need to populate your model with a Departments object that is a list of Departments
I would like to automatically insert username, userid, date such thing from (server side) model in asp.net mvc how do i insert in such model ?
public class Enquiry
{
public int ID { get; set; }
public DateTime Date { get; set; }
[Required]
public string Name { get; set; }
public string Contactno { get; set; }
public string Remarks { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
public string Editdate { get; set; }
public string status { get; set; }
}
public class EnquiryDBContext : DbContext
{
public DbSet<Enquiry> Enquiries { get; set; }
}
How do i insert date from controller or model without having it to be inserted from view ?
my controller is like this
[HttpPost]
public ActionResult Create(Enquiry enquiry)
{
if (ModelState.IsValid)
{
db.Enquiries.Add(enquiry);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(enquiry);
}
ktm,
just populate the date in the HttpGet action and then pass that to the view. here's a snippet:
Controller:
[HttpGet]
public ActionResult Create()
{
Enquiry enquiry = new Enquiry();
enquiry.Date = DateTime.UtcNow;
// set any other required properties
return View(enquiry);
}
in your create view:
// ref to base model
#model yournamespace.Models.Enquiry
// add the date from the controller as a hidden field
#Html.HiddenFor(m => m.Date)
<!-- other properties -->
then, just use your HttpPost actionmethod as before -voila!