I am new to asp.net mvc4 and creating a project in it. I am stuck on the way.
First let me describe about my project. I am creating a product table and each product has some attributes. I have created a ProductAttribute Model and a AttributeValue Model to add attributes and their values. Then I have created a ProductAttributeValue Model to assign the attributes and their values to the Product.
Now my problem is that I want to use the same view to add Attribute and their values. Below are my models:
[Table("ProductAttribute")]
public class ProductAttribute
{
[Key]
[MaxLength(20)]
public string AttributeId { get; set; }
[Required]
[Display(Name = "Attribute Name")]
[MaxLength(100)]
public string AttributeName { get; set; }
[Required]
[Display(Name = "Datatype")]
[MaxLength(50)]
public string AttributeDatatype { get; set; }
[Required]
[Display(Name = "Is Active")]
public bool IsActive { get; set; }
[Required]
[Display(Name = "Attribute Type")]
[MaxLength(30)]
public string AttributeType { get; set; }
}
[Table("AttributeValue")]
public class AttributeValue
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(20)]
public string AttributeId { get; set; }
[Required]
[MaxLength(100)]
public string AttributeName { get; set; }
[Required]
[MaxLength(200)]
public string AttributeVal { get; set; }
public virtual ProductAttribute ProductAttribute { get; set; }
}
How can I insert values to different tables using one view and controller? If there is another way to do the same then please help me about that.
Thanks
I think I understand what you are getting at. First you are going to want to build a View Model. Something like
public Class Tables
{
public List<ProductAttribute> Products { get; set; }
public List<AttributeValue> Values { get; set; }
}
Set those lists from your controller and pass them to the view. On the view you will define the model like
#model Tables
and then in the view build your table in your manner of preference. I have used Html.WebGrid in the past but have been using just foreach loops recently
<table>
foreach(var temp in Model.Products)
{
<tr>
<td>
temp.Name, etc
</td>
</tr>
}
</table>
as for adding and creating I have never been a fan of creating or adding directly in the table and generally what I am showing in the table isn't all of the information that I want from them so I use context menus or edit buttons on the rows and then a add button in a context menu or just outside of the table that will redirect to an edit/add page and then navigate back. Then you can refresh the table with a post back, jquery, refresh a partial view, whatever way fits your situation best. Hopefully this helps :)
Oh, here is a link to people discussing best how to edit a table
How to edit tabular data (ASP MVC)
Update:
Any information passed to the view through the model and used on the page with a for (html.textboxfor, textareafor, etc) will be passed back to the controller. If those fields are changed then the changed value will be passed back.
public ActionResult Index(){
(build your table class)
return View(Tables);
}
[HttpPost]
public ActionResult Index(Tables tbl){
(pass values return from the view to your query for saving to the database)
{
Related
I'm writing an mvc5 application where I have a model called Survey.
public class Survey
{
public int SurveyId { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Classification { get; set; }
[Required]
public int Score1{ get; set; }
[Required]
public int Score2{ get; set; }
public string Notes { get; set; }
}
I'm passing a collection of Survey records to a view where I display them in a list. I want to be able to allow the user to answer each survey record/question and have a save button at the bottom of the form to conduct one POST action back to the controller.
I've never tried to pass a collection of objects back to the POST controller so I'm curious if this is a good approach? Any suggestions is appreciated!
Thanks in advance!
What I would suggest is not passing a collection to the view but a new ViewModel 'SurveySet' with perhaps its only field being IList(Survey). Then in the Controller when you call db.SaveChanges() on the surveySet and all the changes to each of its Surveys should be saved.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateComment(SurveySet surveySet)
{
db.Entry(surveySet).State = EntityState.Modified;
db.SaveChanges();
}
I am currently trying to develop my first .NET MVC application and so learning the main concepts.
In my application I have a table that displays a list of animals from an animals table. In the table I am also trying to display the animal breed, but I am pulling the breed from the Breed table on the foreign key stored in the Animal table
I am currently trying to use a Navigation Property to display the Breed text and not the ID so I
altered my Animal model to look like this
public partial class Animal
{
public int AnimalId { get; set; }
public Nullable<int> UserId { get; set; }
public string TagNo { get; set; }
public Nullable<int> Species { get; set; }
public Nullable<bool> Sex { get; set; }
public Nullable<int> AnimalBreed { get; set; }
public Nullable<System.DateTime> DOB { get; set; }
public Nullable<int> OwnershipStatus { get; set; }
public Nullable<System.DateTime> DateAdded { get; set; }
public Nullable<bool> BornOnFarm { get; set; }
public virtual Breed Breed { get; set; }
}
And my breed model looks like
public partial class Breed
{
public int id { get; set; }
public Nullable<int> SpeciesID { get; set; }
public string Breed1 { get; set; }
}
In my view I am trying to display the Breeds field from my animal model as shown below, but the breed column is just empty
<td>
#Html.DisplayFor(modelItem => item.Breed.Breed1)
</td>
Also finally, here is the code that i am using to send the model to the view
List<Animal> Animal1 = (from animals in db.Animals
where animals.Species == 2 && animals.OwnershipStatus == 1
&& animals.UserId == WebSecurity.CurrentUserId
select animals).ToList();
return View(Animal1);
First, don't pluralize single items. It creates confusion in your code:
public virtual Breed Breed { get; set; }
-or-
public virtual ICollection<Breed> Breeds { get; set; }
The virtual attribute allows lazy-loading (a query to fetch the breed will be issued the first time you try to access it). You pretty much always want to include virtual with the property so Entity Framework does not unnecessarily issue joins if you don't actually end up using the property. However, in this case, you are, so you'll want to tell EF to eager-load it by including .Include("Breed") in your query. However, that's just for optimization; it's not your problem here.
Your problem here is that Razor doesn't know how to display Breed. It's not a normal type, obviously, because you created it. So, what you really need is to display the actual property on Breed that you want:
#Html.DisplayFor(m => m.Breed.Breed1)
There's an alternate method, but it's more complex and probably overkill for this scenario. If you really want to use Breed directly, then you need to define a display template for Breed. You do that by adding a new folder to Views\Shared named DisplayTemplates. Inside that folder, add a view named Breed.cshtml. The name of the view here corresponds to the class name, not the property name. Inside that view, you'd do something like:
#model Namespace.To.Breed
#Html.DisplayFor(m => m.Breed1)
Then, in your view you could just do:
#Html.DisplayFor(m => m.Breed)
And Razor will use the display template to render the appropriate thing. Like I said, it's overkill for this, but in more complex object rendering, it might come in handy.
If lazy loading is not enabled in your DbContext, then you have to explicitly load (or use eager loading) the navigation properties.
See http://msdn.microsoft.com/en-us/data/jj574232.aspx
You'll end-up with something like:
var res = (from animals in db.Animals.Include("Breeds")
where animals.Species == 2 & animals.OwnershipStatus == 1
& animals.UserId == WebSecurity.CurrentUserId
select animals).ToList();
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
I have an order model (shown below)
public class Order
{
//[Key]
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[DisplayName("Order Date")]
public DateTime OrderDate { get; set; }
public virtual ProductSelection ProductSelection { get; set; }
public virtual ShippingDetails ShippingDetails { get; set; }
public virtual BillingDetails BillingDetails { get; set; }
public virtual CardDetails CardDetails { get; set; }
public virtual AccountUser AccountUsers { get; set; }
}
As you can see is made up of a set of other models for example ProductSelection (shown below).
public class ProductSelection
{
public int SimulatorId { get; set; }
public string VersionNumber { get; set; }
[DisplayName("Quantity")]
public int Quantity { get; set; }
[DisplayName("Total Price")]
[ScaffoldColumn(false)]
public decimal TotalPrice { get; set; }
}
The issue I am having is when I post to the Controller which has a parameter of Order, I am unable to obtain any of the values from the sub-models (for example Order.ProductSelection.SimulatorId.)
Any ideas why this isn't working as I having to currently use FormCollection which isn't ideal and better messy.
Looking forward to replies
Steve
1) Silly question but just to make sure....Do you preserve values of your sub model on the view(In the form as hidden or any other input type,make sure name of your hidden are same as your properties name in the model) or in the query string.
Before giving you fully loaded model, model binder looks at different places to load your model like your form collection,rout data and query string
If you are not preserving them in any of these places then model binder has no way to find those values and give you loaded values on controller action.
Basics.. http://dotnetslackers.com/articles/aspnet/Understanding-ASP-NET-MVC-Model-Binding.aspx
2)Your example model seems fine but make sure all properties of your sub model have public access modifier and they must have set in their property declaration.
--->I had same issue before because I had private access modifier for set on those properties and I wasted whole day to figure that out.
3)If nothing works(hope that's not the case) then at last you can write your own model binder.
Here is the good post if you decide to head in that direction
http://buildstarted.com/2010/09/12/custom-model-binders-in-mvc-3-with-imodelbinder/
This is my first post (under my account) and it feels really good to participate..!!
You should apply ForeignAttribute on the ProductSelection property which points the primary key of the ProductSelection class:
[ForeignKey("SimulatorId")]
public virtual ProductSelection ProductSelection { get; set; }
Hope that helps.
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.