I am trying to display a list of dynamic check boxes and allow the user to select one or more. Once returned to the controller, I would need to take the ids of all the checked ones and write a record for each to the database.
Below are the pieces of code that relate to this.
DTO
public class OfficeVisitPartOfBodyDisplay
{
public int PartOfBodyId { get; set; }
public string PartOfBodyName { get; set; }
public bool PartOfBodyChecked { get; set; }
}
Model
public class OfficeVisitModel
{
public OfficeVisitEntity OfficeVisit { get; set; }
public TList<PartOfBodyEntity> PartOfBodies { get; set; }
public TList<OfficeVisitPartOfBodyEntity> OfficeVisitPartOfBodies { get; set; }
public List<OfficeVisitPartOfBodyDisplay> OfficeVisitPartOfBodyDisplays { get; set; }
public string PatientName { get; set; }
}
View (The part in question)
<div data-role="fieldcontain">
<fieldset data-role="controlgroup">
<legend>Pain Area(s):</legend>
<% foreach (OfficeVisitPartOfBodyDisplay officeVisitPartOfBodyDisplay in Model.OfficeVisitPartOfBodyDisplays)
{ %>
<label for="partofbodydisplay<%= officeVisitPartOfBodyDisplay.PartOfBodyId %>"><%= officeVisitPartOfBodyDisplay.PartOfBodyName%></label>
<input type="checkbox" id="partofbodydisplay<%= officeVisitPartOfBodyDisplay.PartOfBodyId%>" name="partofbodydisplay" value="<%= officeVisitPartOfBodyDisplay.PartOfBodyName%>" />
<% } %>
</fieldset>
</div>
Controller, the OfficeVisitPartOfBodyDisplays in the model and the partofbodydisplay always come back with no data.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ActivePainArea(OfficeVisitModel model, OfficeVisitPartOfBodyDisplay[] partofbodydisplay, string submitButton)
{
switch (submitButton)
{
case "Save":
model.Message = "Save Coming Soon";
return View(model);
case "Cancel":
model.Message = "Cancel Coming Soon";
return View(model);
case "Complaint":
return RedirectToAction("ActiveComplaint", new { patientId = model.OfficeVisit.PatientId, readOnly = false });
case "Patient History":
model.Message = "Patient History Coming Soon";
return View(model);
//return RedirectToAction("ActivePatientHistory", new { patientId = model.OfficeVisit.PatientId });
default:
return View(model);
}
}
give this a try:
Controller:
public ActionResult ActivePainArea(OfficeVisitModel officeVisitPartOfBodyDisplay, string submitButton) {
View:
<div data-role="fieldcontain">
<% using (Html.BeginForm()) { %>
<fieldset data-role="controlgroup">
<legend>Pain Area(s):</legend>
<% var i = 0; %>
<% foreach (var officeVisitPartOfBodyDisplay in Model.OfficeVisitPartOfBodyDisplays) { %>
<label for="partofbodydisplay<%= officeVisitPartOfBodyDisplay.PartOfBodyId %>">
<%= officeVisitPartOfBodyDisplay.PartOfBodyName%></label>
<%: Html.CheckBox("OfficeVisitPartOfBodyDisplays[" + i.ToString() + "].PartOfBodyChecked", officeVisitPartOfBodyDisplay.PartOfBodyChecked)%>
<% i++; %>
<% } %>
<input type="submit" value="save" />
</fieldset>
<% } %>
</div>
Also you might want to reference this page for more information:
Phil Haacked Model Binding To A List
Related
I'm struggling with the following:
I have a class Questions:
public class Question
{
public int QuestionID { get; set; }
public string QuestionText { get; set; }
public int CategoryID { get; set; }
public string Explanation { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Answer> Answers { get; set; }
}
and another class Answer:
public class Answer
{
public int AnswerID { get; set; }
public string AnswerText { get; set; }
public string Class { get; set; }
public int QuestionID { get; set; }
public virtual Question Question { get; set; }
}
I want a user to be able to add a question with one or more answers from the same view. I am a newbie and not able to figure this out. At this moment I only have the possibility to create a question linked to a category in the Create view.
This is the QuestionController:
// GET: Questions/Create
public IActionResult Create()
{
ViewData["CategoryID"] = new SelectList(_context.Category, "CategoryID", "CategoryName");
return View();
}
Thanks for your help!
I wirte a demo to show how to add one to many relationship tables in the same view:
model
public class Question
{
public int QuestionID { get; set; }
public string QuestionText { get; set; }
public string Explanation { get; set; }
public virtual ICollection<Answer> Answers { get; set; }
}
public class Answer
{
public int AnswerID { get; set; }
public string AnswerText { get; set; }
public string Class { get; set; }
public int QuestionID { get; set; }
public virtual Question Question { get; set; }
}
public class QA
{
public IList<Answer> answer { get; set; }
public Question question { get; set; }
}
view
#model upload111.Models.QA
<form asp-controller="Home" asp-action="Create" method="post">
<div class="form-group">
<label asp-for="#Model.question.QuestionText"></label>
<input asp-for="#Model.question.QuestionText" />
</div>
<div class="form-group">
<label asp-for="#Model.question.Explanation"></label>
<input asp-for="#Model.question.Explanation" />
</div>
<br />
<div class="form-group">
<div id="inputFormRow" style="width: 35%">
<div class="input-group mb-3">
<br />
<div class="input-group-append"></div>
</div>
</div>
<div id="newRow">
<input type="hidden" id="totalLans" value="0" />
</div>
<button id="addRow" type="button" class="btn btn-info">Add Network</button>
</div>
<button type="submit" id="createButton">Add</button>
</form>
#section Scripts
{
<script>
$("#addRow").click(function ()
{
var rowCount = parseInt($("#totalLans").val());
rowCount++;
$("#totalLans").val(rowCount);
var html = '';
html += '<div id="inputFormRow" style="width: 35%">';
html += '<div class="input-group mb-3">';
//change id attribute to name attribute and modify the name
html += '<input type="text" name="answer[' + (rowCount - 1) + '].AnswerText" class="form-control m-input" placeholder="AnswerText" autocomplete="off" style="width: 30%" required>';
html += '<input type="text" name="answer[' + (rowCount - 1) + '].Class" class="form-control m-input" placeholder="Class" autocomplete="off" style="width: 30%" required>';
html += '<div class="input-group-append">';
html += '<button id="removeRow" type="button" class="btn btn-danger" style="margin-right: 5px">Remove Network</button>';
html += '</div>';
html += '</div>';
$('#newRow').append(html);
});
$(document).on('click', '#removeRow', function ()
{
var rowCount = parseInt($("#totalLans").val());
rowCount--;
$("#totalLans").val(rowCount);
$(this).closest('#inputFormRow').remove();
});
$(document).ready(function () {
$("#createButton").click(function ()
{
var inputData = $('form').serializeArray();
$.ajax(
{
type: "POST", //HTTP POST Method
url: "Home/Create", // Controller/View
data: inputData,
success : function(response) {
console.log(response)
}
});
});
});
</script>
}
controller
public IActionResult Create()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Create(QA q)
{
Question qs = new Question();
qs.QuestionText = q.question.QuestionText;
qs.Explanation = q.question.Explanation;
qs.Answers = new List<Answer>();
foreach (var item in q.answer) {
var A = new Answer()
{
AnswerText = item.AnswerText,
Class = item.Class
};
qs.Answers.Add(A);
}
_context.questions.Add(qs);
_context.SaveChanges();
return RedirectToAction("Index");
}
This is my first post so please be gently..
I'm using vs 2017,asp.net core 2.2
I have problem with method to save object in db menaging ViewModel using repository pattern.
Im trying to save id from table Category in table Offers using by VM. I would like to the Category in Offers view was display as NameCategory in DropDownList, and save value Id to Offers table. This is my files:
class:
public class Offers
{
public int Id { get; set; }
public string Title{ get; set; }
public string Contents{ get; set; }
public int CategoryId { get; set; }
public Category Categorys { get; set; }
public string PicturePath { get; set; }
}
public class Category
{
[Key]
public int CategoryId { get; set; }
public string NameCategory { get; set; }
public IEnumerable<Offers> OffersList { get; set; }
}
ViewModel:
public class OffeersVM
{
public string Title { get; set; }
public string Content { get; set; }
public Category Category{get;set;}
public List<IFormFile> Picture { get; set; }
}
controller:
[HttpPost]
public IActionResult Create(OffeersVM model)
{
if (ModelState.IsValid)
{
string uniqueName = ProcesEditPicture(model);
Offers newOffers = new Offers
{
Title= model.Title,
Content = model.Content,
CategoryId = model.Category,//I think this is not corect...
PicturePath = uniqueName
};
_offer.Add(newOffers);
return RedirectToAction("details", new { id = newOffers.Id });
}
return View();
}
view:
#model OffeersVM
#{
ViewBag.Title = "Add offer.";
}
<form asp-controller="Home" asp-action="Create" method="post" enctype="multipart/form-data">
<div class="form-group">
<label asp-for="Title">Title</label>
<input asp-for="Title" class="form-control" id="exampleFormControlInput1" placeholder="Title">
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label for="exampleFormControlSelect1">Select category.</label>
<select class="form-control" id="exampleFormControlSelect1" asp-for="Category" asp-items="#*I't know what item...?*#">
<option value=" test">Please select category.</option>
</select>
<span asp-validation-for="Category"></span>
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1" asp-for="Content">Content offer.</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="6" asp-for="Content"></textarea>
<span asp-validation-for="Content" class="text-danger"></span>
</div>
<div class="form-group">
<div class="col-sm-10">
<div class="custom-file">
<input multiple asp-for="Picture" class="form-control custom-file-input " />
<label class="custom-file-label ">Picture</label>
</div>
</div>
</div>
<div>
<button type="submit" class="btn btn-outline-success">Add offer</button>
</div>
</form>
I do't know how to use SelectList or List to provide Id Category. If enybody know some good turtorials with repository pater , or (better) can help to solve my problem I'll be wery grateful.
Adam.
P.S
Sorry about my English...
After asp-item should be SelectList or List<SelectListItem> type.
Here is a feasible solution.
First, you can do some change in your OffeersVM:
OffeersVM class:
public class OffeersVM
{
public string Title { get; set; }
public string Content { get; set; }
public int CategoryId { get; set; }
public List<Category> Category { get; set; }
public List<IFormFile> Picture { get; set; }
}
Then in your View,change your select to this:
<select class="form-control" id="exampleFormControlSelect1" asp-for="CategoryId" asp-items="#(new SelectList(Model.Category,"CategoryId","NameCategory"))">
<option value=" test">Please select category.</option>
</select>
I simulated a piece of data for testing:
var vm = new OffeersVM
{
Title = "New OfersVM",
Content = "A OfferVM",
Category = new List<Category>
{
new Category
{
CategoryId=1,
NameCategory="AA",
OffersList=new List<Offers>
{
new Offers{Id=1,CategoryId=1,Contents="few",Title="fdfw"},
new Offers{Id=2,CategoryId=1,Contents="sdgsdg",Title="gsdg"},
}
},
new Category
{
CategoryId=2,
NameCategory="BB",
OffersList=new List<Offers>
{
new Offers{Id=3,CategoryId=2,Contents="hghg",Title="fdfw"},
new Offers{Id=4,CategoryId=2,Contents="sddfj",Title="gsdg"},
}
}
}
Result:
Scenario
I am going to create a simple interface to insert donations from students using Asp.net Core MVC and EF. According to the App, before entering donation I have to display student information (from Student table) by using student's Admission number (Add_No).
Then I have to insert donation data using the same view but using a different submit button to the table Welfare.
Problem:
I tried it as following ways as shown in my code blocks. Insertion is successful. But I couldn't show student info on the screen even though I retrieve them.
Code for View.cshtml
#model Student_Management.Models.Welfare
#{
ViewData["Title"] = "Wcreate";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h4 align="center">Welfare Donation Entry Form</h4>
<hr />
<table>
<tr>
<td>
#using (Html.BeginForm("getStudentInfo", "Payments", FormMethod.Post))
{
<div class="form-group">
<label asp-for="Add_No" class="control-label"></label>
<input asp-for="Add_No" class="form-control" id="t1" name="A" />
<span asp-validation-for="Add_No" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="getStudentInfo" class="btn btn-primary" id="btngetStudentInfo" />
</div>
}
</td>
<td>
<ul>
#if (ViewBag.students != null)
{
#foreach (var std in ViewBag.students)
{
<li>
#std
</li>
}
}
</ul>
</td>
</tr>
</table>
Code for Controller
public class PaymentsController : Controller
{
private readonly ConnectionString _context;
public PaymentsController(ConnectionString context)
{
_context = context;
}
public IActionResult Wcreate(Welfare welfare, string A)
{
int maxR_No = _context.Welfare.Max(p => p.R_No);
maxR_No = maxR_No + 1;
welfare.R_No = maxR_No;
if (ModelState.IsValid)
{
_context.Add(welfare);
_context.SaveChanges();
ModelState.Clear();
}
return View();
}
public ActionResult getStudentInfo(string A)
{
var items = _context.Students.Where(x => x.Add_No == A)
.Select(x => new
{
P1 = x.F_Name,
P2 = x.Class + "-" + x.ClassNo
});//.ToList();
ViewData["students"] = items;
return RedirectToAction("Wcreate");
}
namespace Student_Management.Models
{
public class Welfare
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int R_No { get; set; }
[Required]
public string Add_No { get; set; }
[Required]
public string Grade { get; set; }
[Required]
public string STClassNo { get; set; }
[Required]
public string Month { get; set; }
[Required]
public string Year { get; set; }
[Required]
public string Rs { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public string cmt { get; set; }
As hint given by Jasen, I modified my action method and view as follows.
<td>
#using (Html.BeginForm("getStudentInfo", "Payments", FormMethod.Post))
{
<div class="form-group">
<label asp-for="Add_No" class="control-label"></label>
<input asp-for="Add_No" class="form-control" id="t1" name="A" />
<span asp-validation-for="Add_No" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="getStudentInfo" class="btn btn-primary" id="btngetStudentInfo" />
</div>
}
</td>
<p>#TempData["info"]</p>
<p>#(TempData["info2"] +"-" + TempData["info3"])</p>
Action method
public ActionResult getStudentInfo(string A)
{
var items = _context.Students.Where(x => x.Add_No == A)
.Select(x => new
{
P1 = x.F_Name,
P2 = x.Class,
p3=x.ClassNo
}).ToList();
TempData["info"] = items[0].P1;
TempData["info2"] = items[0].P2;
TempData["info3"] = items[0].p3;
return RedirectToAction("Wcreate");
}
I want to add a create function to my page, it has a buildings page and a rooms page however depending on which building is chosen rooms corresponding to its ID are shown. I have that completed but I wanted to add a create function to add more rooms when in a specific building. I have all the required code for creating/inserting in a partial view but I need to pass in relational value without having to put it in myself. Similar to this action link:
#Html.ActionLink("Edit", "Edit", **new { id=item.Id }**)
Here is my room page:
#model TerminalHost.Models.buildingInfo
#{
ViewBag.Title = "Home Page";
}
<h3>Rooms in: #Model.buildingName</h3>
<ol class="round">
<li class="one">
<h5>Please begin creating your network structure:</h5> <button id="modal-opener">Add a new room</button>
</li>
<li class="two">
</li>
</ol>
#*rooms that are specific to a building are shown here*#
#Html.Partial("rooms", Model.roomId)
<div id="Modal" title="room Details">
#Html.Partial("roomForm", new TerminalHost.Models.roomInfo())
</div>
my displayed rooms partial view:
#model IEnumerable<TerminalHost.Models.roomInfo>
<div class="Container">
#foreach (var item in Model)
{<div class="Box">
<div>
<h4 class="Heading">#item.roomName</h4>
<h4 class="Heading">#item.roomNumber</h4>
<p>#item.roomDesc1</p>
<p>#item.roomDesc2</p>
<p>#item.roomDesc3</p>
</div>
</div>
}
</div>
my roomForm partial view:
#model TerminalHost.Models.roomInfo
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("roomForm", "Home"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>roomInfo</legend>
<div class="editor-label">
#Html.LabelFor(model => model.roomNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.roomNumber)
#Html.ValidationMessageFor(model => model.roomNumber)
</div>
....
//Here I would like the building Id to be passed automatically from the buildingInfo model which is being called in the rooms view
<div class="editor-label">
#Html.LabelFor(model => model.buildingId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.buildingId)
#Html.ValidationMessageFor(model => model.buildingId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
This is the model that I'm using to store data with:
public class buildingInfo
{
public int Id { get; set; }
public int buildingNumber { get; set; }
public String buildingName { get; set; }
public String buildingDesc1 { get; set; }
public String buildingDesc2 { get; set; }
public String buildingDesc3 { get; set; }
public virtual ICollection<roomInfo> roomId { get; set; }
}
Here is the roomInfo model:
public class roomInfo
{
public int Id { get; set; }
public int roomNumber { get; set; }
public String roomName { get; set; }
public String roomDesc1 { get; set; }
public String roomDesc2 { get; set; }
public String roomDesc3 { get; set; }
public int buildingId { get; set; }
//public virtual ICollection<rackInfo> rackId { get; set; }
}
If anymore information is needed please ask and I will provide it.
I was thinking to a solution using ViewDataDictionary but I just realised you can pass the value through the constructor of your object.
So you can try this:
#Html.Partial("roomForm",new TerminalHost.Models.roomInfo { buildingId=Model.Id })
I hope it will help you.
I have seen the other Question. But I prefer to answer here maybe it will solve the second problem. Because there are many solutions. But I think maybe the first I gave doesn't allow you to populate this value for some reason.
Could you try this:using a overload of Html.Partial() method and passing a ViewDataDictionary with the value you want.
You need to change this line:
#Html.Partial("roomForm", new TerminalHost.Models.roomInfo())
To:
#Html.Partial("roomForm", new TerminalHost.Models.roomInfo(), new ViewDataDictionary { {"buildingId", Model.buildingId} } )
And in your partial view, you can retrieve it like this:
#model TerminalHost.Models.roomInfo
#{
ViewBag.Title = "Create";
}
#{
int buildingId = Convert.ToInt32(ViewData["buildingId"]);
}
........
<div class="editor-field">
#Html.TextBoxFor(model => model.buildingId,new {#Value=buildingId })
#Html.ValidationMessageFor(model => model.buildingId)
</div>
I hope by doing in this way it will solve the second problem.
Context: MVC 2 app using EF.
Why does some of this work, but some doesn't? The display name gets set to "Court Name" but no validation is happening, i.e. I don't see the error message. I'm thinking the editor templates are interfering with validation, or else Model.IsValid doesn't work with a complex view model.
Any thoughts?
PARTIAL CLASS:
[MetadataType(typeof(CourtMetaData))]
public partial class Court
{
private class CourtMetaData
{
[Required(ErrorMessage = "Court Name is required")]
[DisplayName("Court Name")]
public System.String CourtName
{
get;
set;
}
}
}
CONTROLLER:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult New(CourtsNewViewModel court)
{
if (ModelState.IsValid)
{
db.AddCourt(court);
return View("List");
}
else
{
return View("New", court);
}
}
VIEW MODEL:
public class CourtsNewViewModel : ViewModelBase
{
public Court Court {get; private set; }
public IEnumerable<CourtType> CourtTypes { get; private set; }
public CourtsNewViewModel()
{
CourtTypes = db.GetAllCourtTypes();
}
}
VIEW:
Html.EditorFor(model => model.Court.CourtName, "LongString")
EDITOR TEMPLATE:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
<div class="editor-row">
<div class="editor-label">
<%= Html.LabelFor(model => model) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model)%>
<%= Html.ValidationMessageFor(model => model) %>
</div>
</div>
Here's the gotcha:
public ActionResult New(CourtsNewViewModel court)
The court variable is already used as you have a Court property on your model.
Now rename the parameter:
public ActionResult New(CourtsNewViewModel courtModel)
Everything should work as expected.