here is my model classes;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ContactFormWithMultipleCheckboxApp.Models {
public class Product {
public int ProductId { get; set; }
[Required, StringLength(50)]
public string ProductName { get; set; }
public string Description { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
public class Message {
public int MessageId { get; set; }
public string From { get; set; }
[Required]
//below one is to validate whether the e-mail address is legit or not
[RegularExpression("\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2,4}\b")]
public string Email { get; set; }
[StringLength(100)]
public string Subject { get; set; }
public string Content { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
}
}
And I have installed MvcScaffolding as nuget package to my app. I am trying to a simple scaffolding with following code;
PM> Scaffold Controller Message
it works and creates my controllers, views and DBContect class. but I have one problem. why does it pluralize my dbset item inside dbcontect class;
public class ContactFormWithMultipleCheckboxAppContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, add the following
// code to the Application_Start method in your Global.asax file.
// Note: this will destroy and re-create your database with every model change.
//
// System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ContactFormWithMultipleCheckboxApp.Models.ContactFormWithMultipleCheckboxAppContext>());
public DbSet<ContactFormWithMultipleCheckboxApp.Models.Message> Messages { get; set; }
}
as you can see it creates the name as Messages but it uses Message on the other places like view and controller.
What is happening here?
In this blog post about MvcScaffolding 0.9.4, Steve Sanderson writes:
"Based on your feedback, controller
names are now pluralized by default
(e.g., you get PeopleController rather
than PersonController for a model of
type Person, unless you explicitly
enter PersonController as the
controller name when scaffolding)"
So by default (or convention) it pluralizes your names unless you tell it not to. You stated that you did that, and it didn't pluralize your controller or views.
I wonder if you also need to tell EntityFramework not to pluralize. See this post, "How to singularize in EntityFramework" for more details about that.
Related
I am developing an application in razor web apps (asp.netcore) and scaffolding db tables using efcore.
I performed a db-scaffold on my OnlineForms data table, which created my OnlineForms.cs Class. When i directly put the [key] attribute on top of the formid property in this class, I can save to the data table without any issues.
But when I move the [key] data annotation into the partial class OnlineFormsValidation, which references OnlineForms, through the [ModelMetadataType] attribute, and I try to save data; I get the error: "The entity type 'OnlineForm' requires a primary key to be defined."
The Required annotations work properly from inside OnlineFormsValidation class, but the [Key] annotation does not.
Thank you in advance. Any help would be greatly appreciated.
OnlineForm.cs:
namespace VehicleTakeHomeApp.Data.Models
{
public partial class OnlineForm {
[Key] <== works if i put it here, but I want to move it to OnlineFormValidation.cs
public int FormId { get; set; }
public string EmployeeId { get; set; }
public string Name { get; set; }
}
}
OnlineFormValidation.cs:
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
namespace VehicleTakeHomeApp.Data.Models
{
[ModelMetadataType(typeof(OnlineFormValidation))]
public partial class OnlineForm
{
}
public class OnlineFormValidation
{
[Key] <== this annotation is not getting picked up, even though the Required annotations below it get picked up.
public int FormId { get; set; }
[Required(ErrorMessage = "Employee ID is required.")]
public string EmployeeId { get; set; }
[Required(ErrorMessage = "Name is required.")]
public string Name { get; set; }
}
}
I had the OnModelCreating method in my dbcontext class commented out. This method contains the HasKey() from the initial db-scaffold.
I uncommented the OnModelCreating method, and now I don't need to add the [Key] annotation, to either class and it works.
It's more of a workaround then a solution, but its works.
I am using Visual Studio Express 2013 for Web (specifically version 12.0.21005.1 REL). This is my first project using VS2013, I've been using VS2012 up until this point.
I am attempting to create a new controller in my asp.net MVC application. I am using Entity Framework 5 with code first (.NET 4.5). I want Visual Studio to create the template for me (you know, a controller with views to read/write/delete etc, rather than write the code myself from scratch).
However, every time I try to create the controller I get the following error message:
Is there some sort of bug in VS 2013? I can't figure out what this means, and restarting VS2013 does not help.
Here are the gory details.... actually it is all very simple since this is a new project with very little code written so far.
My model:
namespace ProfessionalSite.Models
{
public class EntityModels
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class Enrollment
{
public int ID { get; set; }
public string EnrollmentName { get; set; }
public string Credits { get; set; }
}
// Create the class that inherits from DbContext
// The name of this class is also used as the connection string in web.config
public class EFDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
}
}
}
And in my web.config file I have the following
<add name="EFDbContext"
connectionString="Data Source=JONSNA\SQLEXP2012WT;Initial Catalog=ProfessionalSiteDb; Integrated Security=True; MultipleActiveResultSets=True"
providerName="System.Data.SqlClient"/>
within the tags.
Now time to create a controller. I right click on Controllers in the Solution Explorer, and choose to Add a new Controller.
And then
And when I click Add I get
I cant figure out how to get rid of this error. I guess as a workaround I can just type the code myself, but I'd like to know if this is a bug or something I have done wrong. In VS2012 this just worked...
I'd appreciate any help or pointers. Thanks.
You don't need the EntityModels class, See below:
namespace ProfessionalSite.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class Enrollment
{
public int ID { get; set; }
public string EnrollmentName { get; set; }
public string Credits { get; set; }
}
// Create the class that inherits from DbContext
// The name of this class is also used as the connection string in web.config
public class EFDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
}
}
Then when you create a controller, just select the Student or Enrollment for the Model class.
I have a State model class:
public class State
{
public int Id { get; set; }
public string Name { get; set; }
public int CountryId { get; set; }
public virtual Country Country { get; set; }
}
And I am trying to create a Repository:
Scaffold Repository State
I've got in generated file:
public IQueryable<State> All
{
get { return context.State; }
}
instead of context.StateS.
Property
public DbSet<State> States { get; set; }
successfully has been added to the DbContext class.
I have no overrided OnModelCreating method.
Sometimes I mention such problem in different projects but can not find a reason.
I know I've had problems with namespace confusion when using the word "State" for my database tables and POCOs. So to make things easier, I rename those to something else, like USState or StateCode. That could be what's going on here for you and the scaffolding.
I have a Person model and a student model. The student model has 2 FKs of PersonIDs; one for student and the other for parent.
My view looks like this:
#Html.EditorFor(m => m.student.Person.FirstName)
#Html.EditorFor(m => m.student.Person.DOB)
#Html.EditorFor(m => m.student.Father.FirstName)
The models would look like this:
public partial class Person
{
public int PersonID { get; set; }
[Required]
[PlaceHolder("First Name")]
public string FirstName { get; set; }
[PlaceHolder("Birth Date")]
public Nullable<System.DateTime> DOB { get; set; }
}
public partial class Student
{
public int Student_PersonID { get; set; }
public int Parent_PersonID { get; set; }
}
I want the DOB to be required field for the student but not for the parent. If I add [Required] attribute to the DOB element, then it requires it for both. Is there a way I can set a require a field on the view? or is there a way in the model or using validation attribute to do this?
fyi... i am using EF database first approach
thanks
I would suggest having the view model match the fields that are displayed in the view. If later a field is to be removed from the view, then it will also be removed from the domain model.
In this case, if your view is to display the following fields:
StudentFirstName
StudentDOB
ParentFirstName
ParentDOB
Then I would suggest having the following view:
public class PersonViewModel
{
public int StudentPersonID { get; set; }
[Required]
public string StudentFirstName { get; set; }
[Required]
public DateTime StudentDOB { get; set; }
public int ParentPersonID { get; set; }
[Required]
public string ParentFirstName { get; set; }
public DateTime ParentDOB { get; set; }
}
Or if instead you have 2 seperate views displaying:
StudentFirstName
StudentDOB
AND displaying:
ParentFirstName
ParentDOB
Then I would suggest having 2 seperate view models:
public class StudentViewModel
{
public int StudentPersonID { get; set; }
[Required]
public string StudentFirstName { get; set; }
[Required]
public DateTime StudentDOB { get; set; }
}
public class ParentViewModel
{
public int ParentPersonID { get; set; }
[Required]
public string ParentFirstName { get; set; }
public DateTime ParentDOB { get; set; }
}
Using the view models in this way will allow you to use the [Required] data annotations for the fields that require them rather than trying to create a workaround. Note that the view models are not to be confused with the domain models and therefore this data would then need to be mapped to the domain model.
Hope this helps.
If your application is a simple application you may not need to create a seperate business logic layer and most books only present MVC with simple models which may be fine. However, if you search around you will find other examples where developers recommend having a view model seperate from a business model such as this
I would also recommend reading Wrox Professional Enterprise .Net 2009 where chapters 7 & 8 give great examples of the business layer with discussions of the Transaction Script pattern, Active Record pattern and Domain Model pattern.
One way is to make a PersonRequired class that inherits from Person. Add a metadata class to PersonRequired so you have PersonRequiredMetaData and in that specific that the inherited DOB field is required. You would need to manually copy the values between the Person and PersonRequired classes or use AutoMapper. I hope there is a better answer than this!
Another option is to use FluentValidation that would let you do the validation separate from the model (doesn't use data annotations). I wonder if some people are using data annotations for database requirements and fluent validation for programmatic requirements.
I know this works for single properties as per Scott Guthrie's blog to auto-magically use a partial view to render a partial model passed to it (UI Helper like in dynamic data):
[UIHint("StateDropDown")]
public string State { get; set;}
But how do you annotate an entire class to use an UI helper like this:
[UIHint("Address")]
public class Address {
public string addr1 { get; set; }
public string addr2 { get; set; }
public string city { get; set; }
[UIHint("StateDropDown")]
public string state { get; set; }
public string zip { get; set; }
}
(Except [UIHint("Address")] doesn't seem to work on classes. I see in his examples, he has "Customer.aspx" in the Shared->EditorTemplates folder, so I assume this is possible.
Make a template with the name of the class, and it just works.