CRUD Views For Many-Many Relationship, Checkboxes - asp.net-mvc

I am having a hard time trying to figure out what I need to do to get this to work. I'm learning ASP.NET MVC CodeFirst with EF. If I make a model I can simply add a controller for that model and add scaffolding to create views that automatically take care of CRUD. But now I have two models, Project and Category. They have a many to many relationship and database is designed correctly with the associative table without having to make a separate model for it. The code for the models is this....
public class Project
{
public int ProjectId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Testimonial { get; set; }
public virtual ICollection<Image> Images { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public Project()
{
Categories = new HashSet<Category>();
}
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public ICollection<Project> Projects { get; set; }
public Category()
{
Projects = new HashSet<Project>();
}
}
So I add my controllers and do the scaffolding. I go in and create my categories just fine. But when it comes to my Projects/Create view, I would like to make it so that all the categories are displayed as checkboxes. Also, I would like to ensure that at least one category is selected before being able to submit the form to create a project. How would I do this?

For an example of using check boxes in a similar scenario, see Adding Course Assignments to the Instructor Edit Page in this tutorial:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application

Related

how to scaffold more then one class with foreign key in mvc 5?

Is it possible to scaffold more then one class in MVC 5?
I have 2 classes I'd like to been able to edit/create on one page.
Do I have to scaffold separately each class and then connect somehow their views or is there a better way? Let say I have classes Office and Contacts
and want Office data and Contacts for that office to be editable on one page.
Also I do code first approach and not sure how to connect them with foreign key? One office can have many contacts. I have classes as below
thanks
public class Office
{
[Key]
public int Id { get; set; }
public int ContactId { get; set; }
public string OfficeName { get; set; }
}
public class Contact
{
[Key]
public int Id { get; set; }
public int OfficeId { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
It sounds like this would be a good time to use a View Model. Scaffolding is a great way to quickly create views for a given model, but at some point you've got to introduce more robust models to handle scenarios like what you've described. Create another model class (or 'view model' class if you've delegated a folder for those) such as
namespace MyProject.Web.ViewModels
{
public class OfficeContactsVModel
{
public Office OfficeModel { get; set; }
public Contact ContactModel { get; set; }
}
}
Of course, if you are using repository pattern it'll have to be hooked up differently. You could also specify a custom model with values you need for your form and map them to a specific model in a post ActionResult in the controller. There are plenty of ways to achieve what you are looking for.
(Also see: Multiple models in a view and ASP.NET MVC 5 - Scaffolding for Many to One Relationship)

MVC 4 - Scaffolding - Why are my 1:1 and 1:M properties skipped?

I'm very new with MVC 4 and I have the following class:
public class BicycleSellerListing
{
public int BicycleSellerListingId { get; set; }
public UserProfile UserProfile { get; set; }
public System.DateTimeOffset ListingDate { get; set; }
public double ListingPrice { get; set; }
public string BicycleModel { get; set; }
public string Color { get; set; }
public string Comments { get; set; }
public BicycleManufacturer BicycleManfacturer { get; set; }
public BicycleType BicycleType { get; set; }
public BicycleFrameSize BicycleFrameSize { get; set; }
public DateTime ModelYear { get; set; }
public ICollection<BicycleAttribute> BicycleAttributeList { get; set; }
}
When I created a new Controller for this class, I selected the MVC controller with read/write actions and views, using Entity Framework scaffolding option. In the Create.cshtml, it skipped creating editors for all my 1:1 and 1:M properties (BicycleManufacturer, BicycleType etc.). Ideally I would have liked VS to create drop-down list editors for these properties.
Is it possible to have editors created for these properties, or do I need to do it manually?
Complex objects will need some help. Thankfully, this isn't difficult to do, and the MVC Framework is quite customizable in this regard.
The first thing you'll want to do is to create views to handle editing and display. These go in your Editor and Display template folders under Views\Shared.
https://github.com/MisterJames/BootstrappingMvc/tree/master/BootstrappingMvc/Views/Shared
Next, you'll want to decorate your properties on your view models with UIHint to tell MVC what views to use.
https://github.com/MisterJames/BootstrappingMvc/blob/master/BootstrappingMvc/Models/MoviePass.cs
This will help take care of your 1:1. You'll want to look into something like MvcScaffolding to handle your list items, it does a fairly good job
There is a full walkthrough here:
http://jameschambers.com/2012/07/bootstrapping-mvc-say-no-to-checkboxes/
Cheers.

MVC MultiSelect modelbinding

i want to be able to display and update my User's Organisations preferably using the htmlhelper Html.TextBoxFor(
I have an entityframework 5 database first database with relationships defined as expected on the 3 tables
User
Organisation
UserOrganisation
which yield the classes below
public partial class User
{
public System.Guid UserId { get; set; }
public string Fullname { get; set; }
...
}
public partial class Organisation
{
public int OrganisationID { get; set; }
public string Title { get; set; }
...
}
public partial class UserOrganisation
{
public System.Guid UserId { get; set; }
public int OrganisationID { get; set; }
}
I pass in the user as the model and also populate a list of potential organisations in the viewbag i.e.
ViewBag.PossibleOrganisations = OrganisationFactories.GetOrganisations()
and the razor markup is.
#Html.ListBoxFor(model => model.UserOrganisations,
new MultiSelectList(ViewBag.PossibleOrganisations,"OrganisationID","Title"))
Now this displays the list of Organisations correctly and i can multiselect them. But it doesn't show the selected Organisations, and it also wont write this back to the database when posting back (incidentally all other fields did write back prior to this change).
Does anyone have any suggestions or examples of a multiselect list working in this fashion?
Cheers
Tim

Custom Conditional validation on strongly typed view in MVC

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.

How do I display data from multiple tables in a single MVC view

I am having a hard time solving the following with an MVC view.
My goal is to display data from multiple tables in a single MVC view. The bulk of the data comes from a table called Retailers. I also have another table called RetailerCategories which stores the retailerid from the Retailers table and also a categoryid linking to a Category table.
Note that there are multiple records for each retailerid in the RetailerCategories table.
In the view I want to show a list of retailers and with each retailer I want to show the list of categories applicable to them.
What would be the best way to accomplish this? Some of the things I have tried are covered in Can you help with this MVC ViewModel issue?
This however does not appear to be the right approach.
You need a view model specifically tailored to the needs of this view. When defining your view models you shouldn't be thinking in terms of tables. SQL tables have absolutely no meaning in a view. Think in terms of what information you need to show and define your view models accordingly. Then you could use AutoMapper to convert between your real models and the view model you have defined.
So forget about all you said about tables and focus on the following sentence:
In the view I want to show a list of
retailers and with each retailer I
want to show the list of categories
applicable to them.
This sentence is actually very good as it explains exactly what you need. So once you know what you need go ahead and modelize it:
public class CategoryViewModel
{
public string Name { get; set; }
}
public class RetailerViewModel
{
public IEnumerable<CategoryViewModel> Categories { get; set; }
}
Now you strongly type your view to IEnumerable<RetailerViewModel>. From here it is easy-peasy to do what you want in the view:
showing a list of retailers with each retail having a list of associated categories.
this could be also helpful;
video from chris pels
It is simple just do what I say step by step.
add connection string into web.config file
select models from solution explorer and add 4 classes as following
1st class for first table "i have employ table which have 3 columns
public class Employ
{
[Key]
public int Emp_id { get; set; }
public string Emp_name { get; set; }
public string Emp_city { get; set; }
}
2nd class for my tempo table
public class tempo
{
[Key]
public int ID { get; set; }
public int Emp_Id { get; set; }
public string subject { get; set; }
public string hobby { get; set; }
}
Now I create a third class in model folder which contain value that i want from employ table and tempo table
public class Alladd
{
public int ID { get; set; }
public int Emp_Id { get; set; }
public string subject { get; set; }
public string hobby { get; set; }
public string Emp_name { get; set; }
public string Emp_city { get; set; }
}
and the final class is datacontext class
public class DataContext:DbContext
{
public DataContext() : base("DefaultConn")//connection string
{
}
public DbSet<Employ> Empdata { get; set; }
public DbSet<tempo> Tempdata { get; set; }
}
now go to the Home controller and add code as below
public ActionResult file()
{
// IList<tempo> tempi=new List<tempo>();
IEnumerable<Alladd> model = null;
// model = getVerifydetails(id);
// return View(objcpModel);
List<Alladd> verify = new List<Alladd>();
cn.Open();
if (cn.State == ConnectionState.Open)
{
string query = "select Employ.Emp_name,Employ.Emp_id,Employ.Emp_city,tempo.hobby,tempo.id,tempo.subject from Employ inner join tempo on Employ.Emp_id=tempo.Emp_id;";//joining two table
SqlCommand cmd=new SqlCommand(query,cn);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
verify.Add(new Alladd { Emp_name = dr[0].ToString(), Emp_Id= Convert.ToInt32(dr[1].ToString()), Emp_city = dr[2].ToString(), hobby = dr[3].ToString(),ID = Convert.ToInt32(dr[1].ToString()),subject= dr[4].ToString()});//filling values into Alladd class
}
cn.Close();
}
return View(verify);
}
now the final step is so simple
go to solution explorer
select views folder and left click on it and select add view
now name it as "file" which we give it into controller
check on create strongly type view
select model class from dropdown-> Alladd
select scaffold templet ->List
hit Add button
Now you're done
Happy coding...

Resources