SelectList from ViewModel from repository Asp.net core - entity-framework

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:

Related

Associating foreign key on dropdown in Entity Framework Core

I am building a simple college management system where I have two models(right now). The following are my model classes.
public class FacultyModel
{
[Key]
public int s_no { get; set; }
public string name { get; set; }
public string description { get; set; }
public string? file { get; set; }
public string? hod { get; set; }
public ICollection<ProgramModel> ProgramModels { get; set; }
}
public class ProgramModel
{
[Key]
public int s_no { get; set; }
public string name { get; set; }
public string description { get; set; }
public string? file { get; set; }
public string type { get; set; }
public string system { get; set; }
public string? director { get; set; }
public int sem_year { get; set; }
[ForeignKey("fid")]
public FacultyModel faculty { get; set; }
public int fid { get; set; }
}
I have completed the CRUD operations for faculty. Now, While inserting the program(program model), I want the user to select one of the faculty from a dropdown or selectlist and the selected faculty's key will be set in the foreign key of program model. I'm stuck in this
Below is my controller of faculty model
public class AdminFacultyController : Controller
{
private readonly DataContext _context;
public AdminFacultyController(DataContext context, IWebHostEnvironment webHostEnvironment)
{
_context = context;
_webHostEnvironment = webHostEnvironment;
}
private readonly IWebHostEnvironment _webHostEnvironment;
// GET
public async Task<string> UploadImage(string folderpath, IFormFile file)
{
folderpath += file.FileName;
string serverFolder = Path.Combine(_webHostEnvironment.WebRootPath, folderpath);
await file.CopyToAsync(new FileStream(serverFolder, FileMode.Create));
return "/" + folderpath;
}
public IActionResult Index()
{
var data = _context.FacultyModels.ToList();
ViewBag.data = data;
return View();
}
public IActionResult AddFaculty()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddFaculty(FacultyModel facultyModel, IFormFile file)
{
string folder = "file/";
facultyModel.file = await UploadImage(folder, file);
_context.FacultyModels.Add(facultyModel);
_context.SaveChanges();
return RedirectToAction("Index");
}
public async Task<IActionResult> UpdateFaculty(int id)
{
var facultyModel= await _context.FacultyModels.FindAsync(id);
ViewBag.data = facultyModel;
return View(facultyModel);
TempData["ID"] = id;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UpdateFaculty( int id, FacultyModel facultyModel, IFormFile? file, string name, string description)
{
if (file == null)
{
var faculty = _context.FacultyModels.Where(f => f.s_no == id).FirstOrDefault();
faculty.name = facultyModel.name;
faculty.description = description;
await _context.SaveChangesAsync();
}
else
{
string folder = "file/";
facultyModel.file = await UploadImage(folder, file);
_context.FacultyModels.Update(facultyModel);
await _context.SaveChangesAsync();
}
return RedirectToAction("Index");
}
public IActionResult AppointHod()
{
return View();
}
public IActionResult UpdateHod()
{
return View();
}
public IActionResult DeleteFaculty(int id)
{
var data = _context.FacultyModels.Find(id);
_context.FacultyModels.Remove(data);
return RedirectToAction("Index");
}
}
Below is my view containing selectlist for faculty
<form>
<div class="form-group">
<label for="input-1">Type</label>
<select class="form-control" id="input-1" placeholder="Enter type" name="type" required list="faculty">
<datalist id="faculty">
<option > Bachelor </option>
<option > Master</option>
</datalist>
</select>
</div>
<div class="form-group">
<label for="input-2">Faculty</label>
<input type="text" class="form-control" id="input-2" placeholder="Enter semester/year" name="faculty" required list="teacher">
<datalist id="teacher">
<option value="Boston"/>
<option value="Cambridge"/>
</datalist>
</div>
<div class="form-group">
<label for="input-3">Program Name</label>
<input type="text" class="form-control" id="input-3" placeholder="Enter Name" name="name" required>
</div>
<div class="form-group">
<label for="input-4">Description</label>
<input type="text" class="form-control" id="input-4" placeholder="Enter Description" name="description" required>
</div>
<div class="form-group">
<label for="input-5">File(syllabus)</label>
<input type="file" class="form-control" id="input-5" name="file">
</div>
<div class="form-group">
<div class="form-group">
<label for="input-6">System</label>
<select class="form-control" id="input-6" placeholder="Enter type" name="system" required list="system">
<datalist id="system">
<option > Yearly </option>
<option > Semester</option>
</datalist>
</select>
</div>
<div class="form-group">
<label for="input-7">Number of year/sem</label>
<input type="number" class="form-control" id="input-7" placeholder="Enter number of year/sem" name="yearsem" required>
</div>
<button type="submit" class="btn btn-light px-5"> Add</button>
</div>
</form>
I just want to populate the selectlist with name of faculty and Insert the s_no of the selected faculty in program model as foreign key.
Below is a working demo, you can refer to it.
ProgramModel
public class ProgramModel
{
[Key]
public int ProgramModels_no { get; set; }
public string name { get; set; }
public string description { get; set; }
public string? file { get; set; }
public string type { get; set; }
public string system { get; set; }
public string? director { get; set; }
public int sem_year { get; set; }
[ForeignKey("FacultyModels_no")]
public virtual FacultyModel FacultyModel { get; set; }
public int FacultyModels_no { get; set; }
}
FacultyModel
public class FacultyModel
{
[Key]
public int FacultyModels_no { get; set; }
public string name { get; set; }
public string description { get; set; }
public string? file { get; set; }
public string? hod { get; set; }
public virtual ICollection<ProgramModel> ProgramModels { get; set; }
}
In Controller for ProgramModel, I add the below code in create action:
ViewData["Faculty"] = new SelectList(_context.Set<FacultyModel>(), "FacultyModels_no", "name")
In the create view, I add like below:
<div class="form-group">
<label asp-for="FacultyModels_no" class="control-label"></label>
<select asp-for="FacultyModels_no" class ="form-control" asp-items="ViewBag.Faculty"></select>
</div>
result:

How to add/create multiple one-to many relationships in same view in ASP.NET Core MVC

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");
}

How to View data from a different table and Insert data in to another table from one view page using Asp.net core MVC?

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");
}

Multiple models in HTTPPost action returns null

I am having a model called "Request" which has three more model within it as below
public partial class Request
{
public long RequestID { get; set; }
public System.DateTime CreationDate { get; set; }
public string RequesterName { get; set; }
public string RequesterPhone { get; set; }
public virtual AccessLevels AccessLevels { get; set; }
public virtual Department Department { get; set; }
public virtual Project Project { get; set; }
}
Project Model
public partial class Project
{
public long RequestID { get; set; }
public string ProjectName { get; set; }
public virtual Request Request { get; set; }
}
Department Model
public partial class Department
{
public string DepartmentName { get; set; }
public string DepartmentId { get; set; }
public long RequestID { get; set; }
public virtual Request Request { get; set; }
}
AccessLevels Model
public partial class AccessLevels
{
public string AccessId { get; set; }
public string AccessName { get; set; }
public long RequestID { get; set; }
public virtual Request Request { get; set; }
}
Controller Actions
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Request request, [Bind(Exclude = "RequestID")]Department department, [Bind(Exclude = "RequestID")]Project project, [Bind(Exclude = "RequestID")]AccessLevels accesslevels)
{}
View Code
<div class="form-group">
#Html.Label("New", htmlAttributes: new { #class ="control-label col-md-3"})
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreationDate, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.Label(#DateTime.Now.ToShortDateString(), htmlAttributes: new { #style = "padding-top:7px" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RequesterName, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.Label(#System.Security.Principal.WindowsIdentity.GetCurrent().Name, htmlAttributes: new { #style = "padding-top:7px" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RequesterPhone, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.EditorFor(model => model.RequesterPhone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.RequesterPhone, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-5">
#Html.EditorFor(model => model.Department)
</div>
</div>
<div class="form-group">
<div class="col-md-5">
#Html.EditorFor(model=>model.Project)
</div>
</div>
<div class="form-group">
<div class="col-md-5">
#Html.EditorFor(model => model.AccessLevels)
</div>
</div>
When the HTTPPost happens on submit, the models Project and AccessLevels are always null. Only the model Request and Department are getting values. If i change the order of the model in HTTPPost method, then i get the values for the first two arguments and the other two are becoming null.
Please let me know where the issue is happening

AngularJs - Pass data from associated classes and collections

My Meal Class (server-side)
public class Meal
{
public Meal()
{
Fruits = new List<Fruit>();
}
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Fk_VendorId")]
public virtual Vendor Vendor { get; set; }
public int Fk_VendorId { get; set; }
//collection
public virtual ICollection<Fruit> Fruits { get; set; }
}
Form Html:
<div ng-controller="MealCtrl>
<select ng-model="meal.Id" ng-options="meal.Id as meal.Name for meal in Meals"></select>
</div>
<div ng-controller="FruitCtrl>
<select ng-model="???" ng-options="fruit.Id as fruit.Name for fruit in fruits"></select>
</div>
<div ng-controller="VendorCtrl>
<select ng-model="???" ng-options="vendor.Id as vendor.Name for vendor in vendors"></select>
</div>
Question:
How to pass the selected associated class [Vendor] and associated collection [Fruits] to the Meal class on submit?
Move the closing MealCtrl div to the end and add meal.FK_VendorId as the ng-model for vendor.
<div ng-controller="MealCtrl>
<select ng-model="meal.Id" ng-options="meal.Id as meal.Name for meal in Meals"></select>
<div ng-controller="FruitCtrl>
<select ng-model="???" ng-options="fruit.Id as fruit.Name for fruit in fruits"></select>
</div>
<div ng-controller="VendorCtrl>
<select ng-model="meal.Fk_VendorId" ng-options="vendor.Id as vendor.Name for vendor in vendors"></select>
</div>
</div>