Return related table data in MVC view - c#

I'm creating a golf app to store all my rounds of golf and what I have scored.
I am getting an error with the RoundViewModel and the ScoreViewModel where I get the following error,
Error CS1061 'RoundViewModel' does not contain a definition for
'Score' and no accessible extension method 'Score' accepting a first
argument of type 'RoundViewModel' could be found (are you missing a
using directive or an assembly reference?)
The code for the create.
public ActionResult Create()
{
//Get database values
var dbcourse = db.Course.ToList();
//Make selectlist, which is IEnumerable<SelectListItem>
var courseNameDropdownList = new SelectList(db.Course.Select(item => new SelectListItem()
{
Text = item.CourseName.ToString(),
Value = item.CourseId.ToString()
}).ToList(), "Value", "Text");
// Assign the Selectlist to the View Model
var viewCourse = new RoundViewModel()
{
Course = dbcourse.FirstOrDefault(),
// The Dropdownlist values
CourseNamesDropdownList = courseNameDropdownList,
};
return View(viewCourse);
}
The code for the RoundViewModel.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace GolfScore.Models
{
public class RoundViewModel
{
[Key]
public int RoundId { get; set; }
[Display(Name = "Round")]
public int RoundNumber { get; set; }
[Display(Name = "Date round played")]
[DataType(DataType.DateTime)]
public DateTime DateTime { get; set; }
public int? CourseId { get; set; }
public virtual CourseViewModel Course { get; set; }
public IEnumerable<SelectListItem> CourseNamesDropdownList { get; set; }
}
}
the code for the ScoreViewModel
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace GolfScore.Models
{
public class ScoreViewModel
{
[Key]
public int ScoreId { get; set; }
[Range(1 , 20)]
public int ScoreTotal { get; set; }
public int? HoleId { get; set; }
public virtual HoleViewModel Hole { get; set; }
public int? RoundId { get; set; }
public RoundViewModel Round { get; set; }
}
}
and the code for the create view
<dd class="col-sm-10">
<table class="table">
<tr>
<th>Hole</th>
<th>Par</th>
<th>Score</th>
</tr>
#foreach (var item in Model.Course.Holes)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.HoleNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.Par.ParNumber)
</td>
<td>
#Html.DisplayFor(model => Model.Score.ScoreTotal )
<div class="col-md-10">
#Html.EditorFor(model => Model.Score.ScoreTotal, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => Model.Score, "", new { #class = "text-danger" })
</div>
</td>
</tr>
}
</table>
</dd>
I have tried amending the RoundViewModel to include
public int? ScoreId { get; set; }
public virtual ScoreViewModel Score { get; set; }
but this causes the following error:
Unable to determine the principal end of an association between the
types 'GolfScore.Models.ScoreViewModel' and
'GolfScore.Models.RoundViewModel'. The principal end of this
association must be explicitly configured using either the
relationship fluent API or data annotations.'
Any help on how I can get the related score data into my create view is appreciated.

The following error:
Unable to determine the principal end of an association between the types 'GolfScore.Models.ScoreViewModel' and 'GolfScore.Models.RoundViewModel'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.'
Is happening because you're using one to one relationship without specifying which end is the principal in the relationship.
Add a [Required] attribute on the attribute in which you're considering a principal in the relationship.
In your case I think it should be in the ScoreViewModel class. Which mean your class should be like this now:
public class ScoreViewModel
{
[Key]
public int ScoreId { get; set; }
[Range(1 , 20)]
public int ScoreTotal { get; set; }
public int? HoleId { get; set; }
public virtual HoleViewModel Hole { get; set; }
public int? RoundId { get; set; }
[Required]
public RoundViewModel Round { get; set; }
}

Related

Average method not working asp.net core code first:

2 model classes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace CareCompProj.Models
{
public enum Profession { Counsellor, Physio, Doctor }
public class HealthProfessional
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Name")]
public string Name { get; set; }
public bool AcceptsMedicalCard { get; set; }
[Required]
[StringLength(80)]
[Display(Name = "Address")]
public string Address { get; set; }
[Required]
public Profession Profession { get; set; }
public ICollection<Review> HealthReviews { get; set; }
public double CalculateAverageRating()
{
var averageRating = HealthReviews.Average(r => r.Rating);
return averageRating;
}
public ICollection<Client> Clients { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace CareCompProj.Models
{
public class Review
{
public int ID { get; set; }
public int? ClientID { get; set; }
public int? HealthProfessionalID { get; set; }
[Required]
[Range(0, 5, ErrorMessage = "Please select number between 1 and 5")]
public int Rating { get; set; }
[Required]
public string ReviewText { get; set; }
public bool WouldRecommend { get; set; }
public virtual Client Client { get; set; }
public HealthProfessional HealthProfessional { get; set; }
}
}
My 2 problems are
when I use the method created in the Healthprofessional class I get ArgumentNullException: Value cannot be null.
Parameter name: source
e.g
#foreach (var item in Model){
<p> #item.CalculateAverageRating() </p>
}
if I use the ViewBag created in the Healthprofessional Index controller method. This returns Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[<>f__AnonymousType22[CareCompProj.Models.HealthProfessional, System.Double]]
When I go to the page URL where the rating should be.
Here is the ViewBag(created in the healthprofessional controller index method) I reference in the razor view when trying to get the average rating
ViewBag.profRatings = _context.HealthProfessionals.Include(p => p.HealthReviews)
ViewBag.profRatings = _context.HealthProfessionals.Include(p => p.HealthReviews)
.Select(x => new
{
HealthProfessional = x,
RatingAverage = x.HealthReviews.Any() ?
x.HealthReviews.Average(v => (v.Rating)) : 0
});
The razor index view for health professionals uses
#model IEnumerable<CareCompProj.Models.HealthProfessional>
Any help on this would be hugely appreciated. Thanks
You actually need to materialize the result by calling ToList() in your controller action before setting in ViewBag or passing back from request using return View(model) so that the query is executed and result set is populated in the memory in the List<T>.
So for your linq query do:
var model = _context.HealthProfessionals.Include(p => p.HealthReviews)
.Select(x => new
{
HealthProfessional = x,
RatingAverage = x.HealthReviews.Any() ?
x.HealthReviews.Average(v => (v.Rating)) : 0
}).ToList();
Now either pass it back to view when returning like:
return View(model);
or you can set the ViewBag.profRatings and then use it in view.
UPDATE:
you can create a ViewModel specific to your view requirements like:
public class HealthProfessionalVM
{
public HealthProfessional HealthProfessional { get; set; }
public int RatingAverage { get ;set; }
}
and then populate it in controller action instead of creating anonymous object:
var vm = _context.HealthProfessionals.Include(p => p.HealthReviews)
.Select(x => new HealthProfessionalVM
{
HealthProfessional = x,
RatingAverage = x.HealthReviews.Any() ?
x.HealthReviews.Average(v => (v.Rating)) : 0
}).ToList();
return View(vm);
and now strongly type your view to IEnumerable<HealthProfessionalVM> and iterate over it like:
#model IEnumerable<HealthProfessionalVM>
foreach(var item in Model)
{
<p> #item.RatingAverage </p>
}
Hope it helps.

CRUD operations for multiple related records in different tables from single view in MVC C#

I was hoping I could get some assistance on this functionality I am trying to achieve. I have searched, but i do not seem to be able to translate the examples/tutorials I have found to make it work in my own code.
For brevity, let's say I have 2 Models with a one to many relationship between the two. Let's say it is parents and children. One parent can have zero or many children. Each child can only have 1 parent:
namespace MyApp.Models
{
public partial class Parent
{
[Key]
public int parent_id { get; set; }
public string parent_name { get; set; }
public string parent_address { get; set; }
public ICollection<Child> Child { get; set; }
}
public partial class Child { get; set; }
{
[Key]
public int child_id { get; set; }
public int parent_id { get; set; }
public string child_name { get; set; }
public string child_allergies { get; set; }
public virtual Parent parent { get; set; }
}
}
Entity created the tables in the database properly, assigning primary/foreign keys where they needed to be.
I put the common fields in a viewmodel to render them in my view:
using MyApp.Models;
namespace MyApp.ViewModels
{
public class ParentChildViewModel
{
public int parent_id { get; set; }
public string parent_name { get; set; }
public string parent_address { get; set; }
public string child_name { get; set; }
public string child_allergies { get; set; }
}
}
I have my view written as below:
#model MyApp.ViewModels.ParentChildViewModel
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(model => model.parent_name)
#Html.EditorFor(model => model.parent_name)
</div>
<div>
#Html.LabelFor(model => model.parent_address)
#Html.EditorFor(model => model.parent_address)
</div>
<table id="child_table">
#{ Html.RenderPartial("_children"); }
</table>
<div>
<button id="add">Add Child</button>
<button id="rem">Remove Child</button>
</div>
<div>
<input type="submit" value="Create" />
</div>
}
<script type="text/javascript">
$("#add").click(function () {
$.ajax({
url: "#Url.Action("BlankChRow")",
cache: false,
success: function (html) {
$("#child_table").append(html);
}
});
return false;
});
$("#rem").click(function () {
$("#child_table tbody tr:last")
.remove();
return false;
});
</script>
I created a partial view for the child so I can repeat those:
#model MyApp.ViewModels.ParentChildViewModel
#using (Html.BeginCollectionItem("children"))
{
<tr>
<td>
<div>
#Html.LabelFor(model => model.child_name)
#Html.EditorFor(model => model.child_name)
</div>
</td>
<td>
<div>
#Html.LabelFor(model => model.child_allergies)
#Html.EditorFor(model => model.child_allergies)
</div>
</td>
</tr>
}
Then, in my controller (this is where I am stuck):
private ApplicationDbContext db = new ApplicationDbContext();
public ActionResult BlankChRow()
{
return PartialView("_children");
}
public ActionResult Create()
{
return View(new ParentChildViewModel());
}
[HttpPost]
public ActionResult Create(ParentChildViewModel pcvm)
{
var parent = new Parent()
{
parent_id = pcvm.parent_id,
parent_name = pcvm.parent_name,
parent_address = pcvm.parent_address
};
var child = new Child()
{
parent_id = pcvm.parent_id,
child_name = pcvm.child_name,
child_allergies = pcvm.child_allergies
};
if (ModelState.IsValid)
{
db.Parent.Add(parent);
db.Child.Add(child);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(pcvm);
}
I have experimented a few different ways of doing this... but I am unable to get this working the way I would like. Ideally, the View can be brought up, and while they enter the Parent's data, they could add one or many children. The children that are added would each be their own record in the Child table/entity while having the appropriate parent_id.
Any help is appreciated.
I see that you want to generate a list of children for a given parent but your viewmodel doesn't look so.
using MyApp.Models;
namespace MyApp.ViewModels
{
public class ParentChildViewModel
{
public int parent_id { get; set; }
public string parent_name { get; set; }
public string parent_address { get; set; }
public string child_name { get; set; }
public string child_allergies { get; set; }
}
}
Try a viewmodel with a list of children.
Something like this :
using MyApp.Models;
namespace MyApp.ViewModels
{
public class ParentChildViewModel
{
public int parent_id { get; set; }
public string parent_name { get; set; }
public string parent_address { get; set; }
public IEnumerable<Child> children { get; set; }
}
}
I'm supposing here that you just want to iterate over the list. That's why I use the IEnumerable interface instead of the IList interface.
To add a child in the list, you could call the "Create" function of your controller and pass the parent_id of the new child.
In your controller you can therefore create a new child for a given parent in the database using your application context.
Once the database transaction done, you can create a new ParentChildViewModel and fulfill it with the corresponding children and return it to the view.

Displaying data from multiple models on one view (images and text)

Hi everyone so I am trying to create an application using asp.net mvc with a code first database that allows the users to be able to create a blog post with as many images as they wish.I have the data stored in the database but I I am currently trying to have the the head, body and images displaying in the display view this is what I would like it to look like : http://imgur.com/a/IR19r but I am not sure how to accomplish this. I am able to display the head and body but cannot get the images from the image table here is the database diagram: http://imgur.com/a/lvwti
Currently this is the error I get when i add this to the view #Html.DisplayFor(modelItem => item.Images)
An exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: An error occurred while executing the command definition. See the inner exception for details.
Model
public partial class PostModel
{
public PostModel()
{
Images = new List<ImageModel>();
}
[Key]
[HiddenInput(DisplayValue = false)]
public int ID { get; set; }
[Required(ErrorMessage = "Heading is Required")]
[Display(Name = "Heading")]
public string Heading { get; set; }
[Required(ErrorMessage = "Body is Required")]
[DataType(DataType.MultilineText)]
[Display(Name = "Body")]
public string Body { get; set; }
public virtual ICollection<ImageModel> Images { get; set; }
public IEnumerable<HttpPostedFileBase> File { get; set; }
}
public class ImageModel
{
[Key]
public int ID { get; set; }
public string Path { get; set; }
public virtual PostModel Post { get; set; }
public string DisplayName { get; set; }
}
public class ImageVM
{
public int? ID { get; set; }
public string Path { get; set; }
public string DisplayName { get; set; }
public bool IsDeleted { get; set; }
}
public partial class PostVM
{
public PostVM()
{
Images = new List<ImageVM>();
}
public int? ID { get; set; }
public string Heading { get; set; }
public string Body { get; set; }
public IEnumerable<HttpPostedFileBase> Files { get; set; }
public List<ImageVM> Images { get; set; }
}
DbContext
public class EFDbContext : DbContext
{
public DbSet<PostModel> Posts { get; set; }
public DbSet<PostVM> PostVMs { get; set; }
public DbSet<ImageModel> Images { get; set; }
public DbSet<ImageVM> ImageVMs { get; set; }
}
Controller
public ViewResult Display()
{
return View(repository.Posts)
}
View
#model IEnumerable<Crud.Models.PostModel>
#{
ViewBag.Title = "Index";
}
#foreach (var item in Model)
{
<div>
#Html.DisplayFor(modelItem => item.Heading)
</div>
<div>
#Html.DisplayFor(modelItem => item.Body)
</div>
<div>
#Html.DisplayFor(modelItem => item.Images)
#*<img class="img-thumbnail" width="150" height="150" src="/Img/#item.Images" />*#
</div>
}
Here is alternative controller I tried but am not using as I got this error when i tried let Images = i.Path and wasn't really sure if this was meant to be how it was done
Cannot implicity convert typeCrud 'string' to 'System.Collections.Generic.List Crud.Models.ImageVm '
public ViewResult Display()
{
IEnumerable<PostVM> model = null;
model = (from p in db.Posts
join i in db.Images on p.ID equals i.Post
select new PostVM
{
ID = p.ID,
Heading = p.Heading,
Body = p.Body,
Images = i.Path
});
return View(model);
}
item.Images is a collection. So loop through that and display the images.
<div>
#foreach(var image in item.Images)
{
<img src="#image.Path" />
}
</div>
You need to make changes to the src property depending on what value you store in the Path property of image.
You can correct your other action method like this
public ViewResult Display()
{
var posts = db.Posts.Select(d => new PostVM()
{
ID = d.ID ,
Heading = d.Heading,
Body = d.Body,
Images = d.Images.Select(i => new ImageVM() { Path = i.Path,
DisplayName = i.DisplayName }
).ToList()
}).ToList();
return View(posts);
}
Now since you are returning a list of PostVM, make sure your Display view is strongly typed to that.
#model List<PostVM>
<h1>Posts</h1>
#foreach(var p in Model)
{
<h3>#p.Heading</h3>
<p>#p.Body</p>
#foreach(var image in item.Images)
{
<img src="#image.Path" />
}
}
Also, there is no point in keeping the view model classes on your db context. Keep only your entity models. View models are only for the use of UI layer.
public class EFDbContext : DbContext
{
public DbSet<PostModel> Posts { get; set; }
public DbSet<ImageModel> Images { get; set; }
}

Asp.net ViewModel returning null

I am fairly new to Asp.Net Mvc5 as well as c# and I am hoping to acquire a few pointers here, I have been trying to figure out why I was getting the following error :
The model item passed into the dictionary is of type 'System.Data.Entity.DbSet1[SoccerTeams.Models.Player]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[SoccerTeams.Models.ViewModels.TeamViewModel]'.
However now after debugging I realized that the ViewModel object is actually returning null values for all the items. I have created a page that works correctly for adding a team as well as players for that team. In my database the teams has one table and all the players are in another table which each player has the teams name with it (player and team name are in two separate columns) so it can be associated with the correct team. I have created a ViewModel and I am attempting to call that ViewModel and be able to return all the players to the view so I can show them in a list.
My Team controller for the "View all players view" is as follows:
public ActionResult ViewAllPlayers()
{
TeamViewModel teamView = new TeamViewModel();
return View(teamView);
}
My Team Model is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace SoccerTeams.Models
{
// This teams class will be used to represent the teams in the database
public class Team
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string TeamName { get; set; }
public string Coach { get; set; }
public string Conference { get; set; }
}
}
My Player Model is as follows:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace SoccerTeams.Models
{
public class Player
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public Guid TeamId { get; set; }
public string Name { get; set; }
}
}
My ViewModel is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace SoccerTeams.Models.ViewModels
{
public class TeamViewModel
{
public string TeamName { get; set; }
public string Coach { get; set; }
public string Conference { get; set; }
public List<Player> Players { get; set; }
}
}
My CreateTeam action is as follows:
public async Task<ActionResult> Create(TeamViewModel model, string addfiverows)
{
if (ModelState.IsValid)
{
if (!string.IsNullOrEmpty(addfiverows)) return View(model);
var team = new Team { TeamName = model.TeamName, Coach = model.Coach, Conference = model.Conference };
db.Teams.Add(team);
var result = await db.SaveChangesAsync();
if(result > 0)
{
foreach(var player in model.Players)
{
var p = new Player { Name = player.Name, Id = team.Id };
db.Players.Add(p);
}
result = await db.SaveChangesAsync();
}
if(result > 0) return RedirectToAction("Index");
}
return View();
}
My View I am trying to display on is as follows:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#model SoccerTeams.Models.ViewModels.TeamViewModel
#{
ViewBag.Title = "View All Players";
}
<h2>View All Players</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.TeamName)
</th>
<th>
#Html.DisplayNameFor(model => model.Players)
</th>
<th></th>
</tr>
#foreach (var item in Model.Players)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.TeamName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Players)
</td>
</tr>
}
</table>
From researching I thought the problem had something to do with the #model IEnumerable<SoccerTeams.Models.ViewModels.TeamViewModel>. However after talking with #Tony Bao challenging my understanding I noticed that the Viewmodel is actually returning the fields however with null values.
I am also seeking any guides or tutorials as I am not only looking for a solution but also a better understanding of why this happens and how to use the ViewModel properly.
First add Player collection to Team model:
public class Team
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string TeamName { get; set; }
public string Coach { get; set; }
public string Conference { get; set; }
public virtual ICollection<Player> Players { get; set; }
}
and in Player model add Team:
public class Player
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string Name { get; set; }
public Guid TeamId { get; set; }
public virtual Team Team {get; set;}
}
and in ViewAllPlayers action:
public ActionResult ViewAllPlayers(Guid id)
{
var team = db.Teams.Include(t => t.Players).Single(t => t.Id == id);
TeamViewModel teamView = new TeamViewModel
{
TeamName = team.TeamName,
Coach = team.Coach,
Conference = team.Conference,
Player = new List<Player>(team.Players)
};
return View(teamView);
}
You can view DisplayFor Templates in your scenario. There are tons of materials on displaytemplates(for display) and editortempates(for insert and update). you can search on google
Here what i will propose
public ActionResult ViewAllPlayers()
{
//this should be from your database
var teamviewer = new TeamViewModel();
teamviewer.TeamName = "t1";
teamviewer.Players = new List<Player>() { new Player { PlayerName = "p1" }, new Player { PlayerName = "p2" } };
return View();
}
Your view Models
public class TeamViewModel
{
public string TeamName { get; set; }
public string Coach { get; set; }
public string Conference { get; set; }
public List<Player> Players { get; set; }
}
public class Player
{
public string PlayerName { get; set; }
}
Create a Displayfor template here
Views/Shared/DisplayTemplates/Player.cshtml
Player.cshtml
#model SoccerTeams.Models.Player
#Html.DisplayFor(m=>m.PlayerName)
On your index page
#model SoccerTeams.Models.TeamViewModel
<h2>View All Players</h2>
<table class="table">
<tr>
<td>
#Html.DisplayFor(modelItem => modelItem.TeamName)
</td>
<td>
#Html.DisplayFor(modelItem=>modelItem.Players)
</td>
</tr>
</table>

How to save data dynamically from a View in MVC5

I want to build a Questionnaire MVC5 project.
I have a MSSQL database with several tables like: Employee, Questions, Results ...
I made a new MVC5 project, I add it the model base on my database and I manage all CRUD operations need it.
Now I made an view for Questionar :
#model IEnumerable<ChestionarMVC.Models.FormQuestion>
#{
ViewBag.Title = "Chestionar";
}
<h2>Chestionar</h2>
#foreach (var item in Model)
{
#Html.Partial("_Chestionar",item)
}
<input id="Submit1" type="submit" value="submit" />
And a partialView to show each question with 2 text area, one for the answer and one for some aditional info :
#model ChestionarMVC.Models.FormQuestion
<table border="1" style="width:100%">
<tr>
<td>
#Html.DisplayFor(modelItem => Model.Question)
</td>
</tr>
<tr>
<td>
Raspuns <br />
<textarea id="TextArea1" rows="2" cols="80" style="width:800px; height:100px;"></textarea>
</td>
</tr>
<tr>
<td>
Document <br />
<textarea id="TextArea2" rows="2" cols="80" style="width:400px"></textarea>
</td>
</tr>
</table>
Now I want to save in the tblResults the QuestionID, Answer and Document.
In webforms I made a usercontrol, then I used Foreach usercontrol , and saved to database.
In MVC how can I save all?
This is the QuestionsModel:
namespace ChestionarMVC.Models
{
using System;
using System.Collections.Generic;
public partial class FormQuestion
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public FormQuestion()
{
this.FormResults = new HashSet<FormResult>();
this.TBLPos = new HashSet<TBLPos>();
}
public int idQuestion { get; set; }
public string Question { get; set; }
public int idCategory { get; set; }
public int idPosition { get; set; }
public Nullable<int> Ordine { get; set; }
public virtual FormCategory FormCategory { get; set; }
public virtual Formular Formular { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<FormResult> FormResults { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<TBLPos> TBLPos { get; set; }
}
}
this is the ResultsMOdel:
namespace ChestionarMVC.Models
{
using System;
using System.Collections.Generic;
public partial class FormResult
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public FormResult()
{
this.Documentes = new HashSet<Documente>();
}
public int idResult { get; set; }
public int idUser { get; set; }
public int idQuestion { get; set; }
public string Answer { get; set; }
public string RefferenceDocument { get; set; }
public Nullable<System.DateTime> StampDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Documente> Documentes { get; set; }
public virtual Employee Employee { get; set; }
public virtual FormQuestion FormQuestion { get; set; }
}
}
this is the Questionnaire ActionResult used to generate the Questionnaire-View:
public ActionResult Chestionar()
{
var formQuestions = db.FormQuestions;
return View(formQuestions.ToList());
}
Start by creating a view model containing the properties you want for the view (note add other validation attributes as required to suit your needs)
public class QuestionVM
{
public int ID { get; set; }
public string Question { get; set; }
[Required(ErrorMessage = "Please enter and answer")]
public string Answer { get; set; }
public string Document { get; set; }
}
Then create an EditorTemplate. In /Views/Shared/EditorTemplates/QuestionVM.cshtml
#model QuestionVM
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.Question)
#Html.DisplayNameFor(m => m.Question)
#Html.DisplayFor(m => m.Question)
#Html.LabelFor(m => m.Answer)
#Html.TextAreaFor(m => m.Answer)
#Html.ValidationMessageFor(m => m.Answer)
... // ditto for Document (as for Answer)
And in the main view
#model IEnumerable<QuestionVM>
#using (Html.BeginForm())
{
#Html.EditorFor(m => m)
<input type="submit" ... />
}
Note that the EditorFor() method will generate the html for each Question based on the template, and importantly will add the correct name attributes that enable your form controls to be posted back and bound to your model
The in the controller
public ActionResult Chestionar()
{
// Get data model and map to view models
var model = db.FormQuestions.Select(q => new QuestionVM()
{
ID = q.idQuestion,
Question = q.Question,
Answer = .....,
Document = .... // see notes below
};
return View(model);
}
[HttpPost]
public ActionResult Chestionar(IEnumerable<QuestionVM> model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Get the data model again, map the view model properties back to the data model
// update properties such as user and date
// save and redirect
}
Side note: your question indicates an (one) Answer and Document for each question, yet you current models for the Question have a collection (ICollection<FormResult> FormResults) containing properties for the Answer and RefferenceDocument so its not clear if you want to add multiple answers and documents for each Question, or just one.

Categories