Blazor creating a generic drop-down - components

I'm trying to create a generic dropdown component for use across our system. However, I'm encountering issues when binding the EventCallback for when the selected item is changed.
This is my current musings for the generic drop down:
<div class="inputItem #(SizeClass) dropdown" style="min-width:#(Width);">
<SfDropDownList TItem="object" TValue="int" Placeholder="Select a category" DataSource="DataSource" Value="#(SelectedItem)" EnableVirtualization="true">
<DropDownListEvents TItem="object" TValue="int" ValueChange="#OnSelectedItemChanged"></DropDownListEvents>
<DropDownListFieldSettings Text="#(TextField)" Value="#(ValueField)" />
</SfDropDownList>
</div>
#code {
[Parameter]
public IEnumerable<object> DataSource { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs<int, object>> OnSelectedItemChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string TextField { get; set; }
[Parameter]
public int SelectedItem { get; set; }
[Parameter]
public string ValueField { get; set; }
[Parameter]
public string Width { get; set; }
[Parameter]
public string SizeClass { get; set; }
}
And here's one example component that would call it:
#page "/news/create"
#inject NavigationManager NavManager;
#using Microsoft.EntityFrameworkCore;
#inject IDbContextFactory<FIS2_DbContext> contextFactory;
#inject IFileService fileService;
#using FIS2withSyncfusion.Controls;
#using FIS2withSyncfusion.Models;
#using FIS2withSyncfusion.Utility;
#using Syncfusion.Blazor.RichTextEditor;
#using System.Collections.Generic;
#using System.Threading.Tasks;
#using Newtonsoft.Json;
<div class="dashWrapper">
<SfDashboardLayout AllowDragging="false" AllowFloating="false" AllowResizing="false" CellAspectRatio="2.5" CellSpacing="#(new double[]{20,20})" Columns="3">
<DashboardLayoutPanels>
<DashboardLayoutPanel Column="0" Row="0" SizeX="2" SizeY="2" Id="createNews">
<HeaderTemplate>
<h3>Create A News Item</h3>
</HeaderTemplate>
<ContentTemplate>
<div class="form-wrapper">
<div class="inputRow">
<TextBox AutoComplete="#(Syncfusion.Blazor.Inputs.AutoComplete.Off)" Placeholder="Title" Text="#(title)" HTMLAttributes="#textboxValidation" Width="450px" SizeClass="half-width"></TextBox>
<DropDownList DataSource="categories" Placeholder="Select a category" SizeClass="half-width" Width="450px" TextField="name" ValueField="id" SelectedItem="#(itemModel.Category)" OnSelectedItemChanged="#(OnSelectedItemChanged)"></DropDownList>
#*<SfDropDownList TItem="spGetNewsCategoriesResult" TValue="int" Placeholder="Select a category" #ref="sfDropDown" DataSource="categories" CssClass="inputItem half-width" #bind-Value="#(itemModel.Category)">
<DropDownListFieldSettings Text="name" Value="id" />
</SfDropDownList>*#
</div>
<div class="inputRow">
<CheckBox Checked="isChecked" Label="Suggest Dates This Should Be Active?" OnCheckChange="#(OnCheckChange)" SizeClass="one-third" Width="300px"></CheckBox>
#if (isChecked)
{
<DateTimePicker Label="Active From:" SelectedDate="#activeFrom" Width="450px" SizeClass="one-third"></DateTimePicker>
<DateTimePicker Label="Active To:" SelectedDate="#activeTo" Width="450px" SizeClass="one-third"></DateTimePicker>
}
</div>
<div class="inputRow">
<FileUploader MaxSize="#(MaxSize)" OnClearFiles="OnClearFiles" OnFileRemove="OnFileRemove" OnFileUpload="OnFileUpload" SizeClass="full-width" Width="400px"></FileUploader>
</div>
<RichTextEditor DeniedAttributes="#DeniedAttributes" text=#(itemModel.Content) Height="400px" Width="1600px"></RichTextEditor>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
</div>
#if (ShowDialog)
{
<Dialog Title="Create News Item" message="#Message" OKText="#OKText" cancelText="#CancelText" OnClose="OnDialogClose">
</Dialog>
}
#code {
[CascadingParameter]
Task<AuthenticationState> authenticationStateTask { get; set; }
public string userName { get; set; }
private int MaxSize { get; set; }
private string title { get; set; }
private int selectedCategory { get; set; }
private string content { get; set; }
int count { get; set; }
private bool ShowDialog { get; set; } = false;
private string Message { get; set; } = "";
private string OKText { get; set; } = "";
private string CancelText { get; set; } = "";
public DateTime activeTo { get; set; }
public DateTime activeFrom { get; set; }
private bool isChecked { get; set; }
SaveNewsItemModel itemModel = new SaveNewsItemModel();
List<string> DeniedAttributes = new List<string>() {
"id", "title", "style"
};
Dictionary<string, object> textboxValidation = new Dictionary<string, object>(){
{"maxlength", "100"}
};
List<spGetNewsCategoriesResult> categories = new List<spGetNewsCategoriesResult>();
private async Task OnCheckChange(bool check)
{
isChecked = check;
StateHasChanged();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var authState = await authenticationStateTask;
var user = authState.User;
userName = user.Identity.Name;
var context = contextFactory.CreateDbContext();
var procedures = context.Procedures;
categories = await procedures.spGetNewsCategoriesAsync();
MaxSize = 15 * 1024 * 1024;
}
}
private List<ToolbarItemModel> Tools = new List<ToolbarItemModel>() {
new ToolbarItemModel()
{
Command = ToolbarCommand.Bold
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Italic
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Underline
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Undo
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Redo
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.OrderedList
},
new ToolbarItemModel()
{
Command = ToolbarCommand.UnorderedList
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.FontColor
},
new ToolbarItemModel()
{
Command = ToolbarCommand.CreateLink
},
new ToolbarItemModel()
{
Command = ToolbarCommand.RemoveLink
}
};
private async Task OnFileUpload(UploadChangeEventArgs args)
{
foreach (var file in args.Files)
{
var fileName = file.FileInfo.Name;
using (var ms = file.Stream)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
int count = 1;
string tempFileName = fileName;
while (fileService.TempFileExists(tempFileName))
{
tempFileName = $"({count}) {fileName}";
count++;
}
var bytes = ms.ToArray();
await fileService.SaveFileToTempAsync(bytes, tempFileName);
var mimetype = fileInfo.Extension;
itemModel.AddFile(fileName, mimetype, tempFileName, contextFactory);
}
}
}
private async Task OnClearFiles(ClearingEventArgs args)
{
foreach (var file in args.FilesData)
{
var fileName = file.Name;
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
itemModel.RemoveFile(fileName, fileInfo.Extension, contextFactory, fileService);
}
}
private async Task OnFileRemove(RemovingEventArgs args)
{
foreach (var file in args.FilesData)
{
var fileName = file.Name;
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
itemModel.RemoveFile(fileName, fileInfo.Extension, contextFactory, fileService);
}
}
private async Task OnSelectedItemChanged(ChangeEventArgs<int, spGetNewsCategoriesResult> eventArgs)
{
itemModel.Category = eventArgs.Value;
StateHasChanged();
}
private async Task OnSave()
{
if (isChecked)
{
itemModel.RequestDates(activeFrom, activeTo);
}
var context = contextFactory.CreateDbContext();
var procedures = context.Procedures;
var addedFiles = await procedures.spCreateNewsItemAsync(JsonConvert.SerializeObject(itemModel), userName);
if (addedFiles.Count > 0)
{
foreach (var file in addedFiles)
{
await fileService.MoveTempToNewsAsync(file.fileName, file.newsID, file.fileID);
}
}
Message = "This has been successfully saved and is now pending review; pressing OK will refresh the page.";
OKText = "OK";
ShowDialog = true;
}
private async Task OnDialogClose(bool r)
{
ShowDialog = false;
NavManager.NavigateTo(NavManager.Uri, true);
}
}
My issue is that I'm getting an error at this point: OnSelectedItemChanged="#(OnSelectedItemChanged)"
The error is:
Cannot convert from method group to EventCallback
The hunting I've done seems to imply that I need to explicitly pass the type in as a parameter, instead of using object and trying to infer it at runtime - I'm just a bit woolly on the details of how to do that?
TValue being an int is something that shouldn't change anywhere. But the TItem could be just about anything (in this particular scenario it's a spGetNewsCategoriesResult) - how do I cater for that?

After much hunting and tinkering, I've found the solution. By changing the component to this:
#typeparam T
<div class="inputItem #(SizeClass) dropdown" style="min-width:#(Width);">
<SfDropDownList TItem="T" TValue="int" Placeholder="Select a category" DataSource="DataSource" Value="#(SelectedItem)" EnableVirtualization="true">
<DropDownListEvents TItem="T" TValue="int" ValueChange="#OnSelectedItemChanged"></DropDownListEvents>
<DropDownListFieldSettings Text="#(TextField)" Value="#(ValueField)" />
</SfDropDownList>
</div>
#code {
[Parameter]
public IEnumerable<T> DataSource { get; set; }
[Parameter]
public EventCallback<Syncfusion.Blazor.DropDowns.ChangeEventArgs<int, T>> OnSelectedItemChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string TextField { get; set; }
[Parameter]
public int SelectedItem { get; set; }
[Parameter]
public string ValueField { get; set; }
[Parameter]
public string Width { get; set; }
[Parameter]
public string SizeClass { get; set; }
}
And referencing it as such:
<DropDownList DataSource="categories" Placeholder="Select a category" SizeClass="half-width" Width="450px" TextField="name" ValueField="id" SelectedItem="#(itemModel.Category)" OnSelectedItemChanged="#(OnSelectedItemChanged)" T="spGetNewsCategoriesResult"></DropDownList>
The error is resolved. Decided to answer my own question as opposed to just deleting it because I figured it'll probably pop up for people on their own search.

Related

The challenge of uploading image. Other information are submitting to the database but the image is not uploading

This is the class of the customer
namespace test2.Models
{
public class Customer
{
public int Id { get; set; }
public string Full_Name { get; set; }
public Driver Driver { get; set; }
[Required]
[Display(Name = "Route")]
public int DriverId { get; set; }
[DataType(DataType.ImageUrl)]
[DisplayName("Driver's License ")]
public string ImageUrl { get; set; }
}
}
Controller
[HttpPost]
public ActionResult Save(Customer customer, HttpPostedFileBase file)
{
if (!ModelState.IsValid)
{
var viewModel = new CustomerFormViewModel
{
Customer = customer,
Drivers = _context.Drivers.ToList()
};
string imageLocation = "";
if ((file == null || file.ContentLength < 1))
{
ViewBag.Msg = "Please select an image";
return View();
}
if (!SaveImg(file, out imageLocation))
{
ViewBag.Msg = "An error occured while saving the image";
}
customer.ImageUrl = imageLocation;
return View("CustomerForm", viewModel);
}
//customer.ImageUrl = imageLocation;
if (customer.Id == 0)
_context.Customers.Add(customer);
else
{
var customerInDb = _context.Customers.Single(d => d.Id == customer.Id);
customerInDb.Full_Name = customer.Full_Name;
customerInDb.DriverId = customer.DriverId;
customerInDb.ImageUrl = customer.ImageUrl;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
public bool SaveImg(HttpPostedFileBase file, out string imageLocation)
{
imageLocation = "";
string serverPath = Server.MapPath("~/Images");
if ((file == null || file.ContentLength < 1))
{
//throw an exception showing that no file is present
}
var imageString = file.ToString();
var allowedExtensions = new[]
{
".jpg", ".png", ".jpg", ".jpeg"
};
var fileName = Path.GetFileName(file.FileName); //eg myImage.jpg
var extension = Path.GetExtension(file.FileName); //eg .jpg
if (allowedExtensions.Contains(extension.ToLower()))
{
string ordinaryFileName = Path.GetFileNameWithoutExtension(file.FileName);
string myFile = ordinaryFileName + "_" + Guid.NewGuid() + extension;
var path = Path.Combine(serverPath, myFile);
file.SaveAs(path);
string relativePath = "~/Images/" + myFile;
imageLocation = relativePath;
return true;
//return a success message here
}
else
{
//file save error
return false;
}
}
Include the file as part of the model:
public class Customer
{
public int Id { get; set; }
public string Full_Name { get; set; }
public Driver Driver { get; set; }
[Required]
[Display(Name = "Route")]
public int DriverId { get; set; }
[DataType(DataType.ImageUrl)]
[DisplayName("Driver's License ")]
public string ImageUrl { get; set; }
[NotMapped]
public HttpPostedFileBase ImageFile { get; set; }
}
Reference in the view like so:
#using (Html.BeginForm("Save", "Image", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.TextBoxFor(model => model.ImageFile, new { htmlAttributes = new { #class = "form-control" }, type = "file" })
</div>
The not mapped property will ensure it is ignored in the db context. It can then be accessed using:
[HttpPost]
public bool Save(Customer customer)
{
if (customer.ImageFile != null)
{
// do something
}
}
It wouldn't be good practise to save the file to the database. Instead, store it in the project directory and either store the name or the image of the path to the image in the database.

ASP.Net MVC: How to show checkboxes selection in webgrid column after postback data

I have developed a tabular UI with webgrid. i am showing student information through webgrid. i am showing multiple checkboxes for hobbies in each row of webgrid. when i select hobbies and click submit button then i saw hobbies selection is not going to action.
i guess there is my mistake in view model class design. please have a look at my code and tell me which area i need to change in code.
i want all hobbies should go to action when i click submit button and selected hobbies also should post to action for each student. a student may have multiple hobbies selected.
here is my viewcode
#model MVCCRUDPageList.Models.StudentListViewModel
#{
ViewBag.Title = "Index";
}
<h2>Student View Model</h2>
#using (Html.BeginForm("Index", "WebGridMoreControls", FormMethod.Post))
{
var grid = new WebGrid(Model.Students, canSort: false, canPage: false);
var rowNum = 0;
var SelectedHobbies = 0;
<div id="gridContent" style=" padding:20px; ">
#grid.GetHtml(
tableStyle: "table",
alternatingRowStyle: "alternate",
selectedRowStyle: "selected",
headerStyle: "header",
columns: grid.Columns
(
grid.Column(null, header: "Row No", format: item => rowNum = rowNum + 1),
grid.Column("ID", format: (item) => #Html.TextBoxFor(m => m.Students[rowNum - 1].ID, new { #class = "edit-mode" })),
grid.Column("Name", format: (item) => #Html.TextBoxFor(m => m.Students[rowNum - 1].Name, new { #class = "edit-mode" })),
grid.Column("Country", format: (item) =>
#Html.DropDownListFor(x => x.Students[rowNum - 1].CountryID,
new SelectList(Model.Country, "ID", "Name", item.CountryID),
"-- Select Countries--", new { id = "cboCountry", #class = "edit-mode" })),
grid.Column(header: "Hobbies",
format: #<text>
Hobbies
#foreach (var hobby in Model.Hobbies)
{
<div class="checkbox">
<label>
#Html.HiddenFor(e => e.Hobbies)
<input type="checkbox"
name="Hobbies"
value="#hobby.ID" /> #hobby.Name
</label>
</div>
}
</text>)
))
<input type="submit" value="Submit" />
</div>
}
Action code
public class WebGridMoreControlsController : Controller
{
// GET: WebGridMoreControls
public ActionResult Index()
{
StudentListViewModel osvm = new StudentListViewModel();
return View(osvm);
}
[HttpPost]
public ActionResult Index(StudentListViewModel oStudentListViewModel)
{
return View(oStudentListViewModel);
}
}
View model code
public class StudentListViewModel
{
public IList<Student> Students { get; set; }
public List<Country> Country { get; set; }
public IList<Hobby> SelectedHobbies { get; set; }
public IList<Hobby> Hobbies { get; set; }
public StudentListViewModel()
{
Students = new List<Student>
{
new Student{ID=1,Name="Keith",CountryID=0,Hobby=0},
new Student{ID=2,Name="Paul",CountryID=2,Hobby=0},
new Student{ID=3,Name="Sam",CountryID=3,Hobby=0}
};
Country = new List<Country>
{
new Country{ID=1,Name="India"},
new Country{ID=2,Name="UK"},
new Country{ID=3,Name="USA"}
};
Hobbies = new List<Hobby>
{
new Hobby{ID=1,Name="Football"},
new Hobby{ID=2,Name="Hocky"},
new Hobby{ID=3,Name="Cricket"}
};
}
}
Model code
public class Student
{
public int ID { get; set; }
[Required(ErrorMessage = "First Name Required")]
public string Name { get; set; }
public int CountryID { get; set; }
public int Hobby { get; set; }
}
public class Country
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Hobby
{
public int ID { get; set; }
public string Name { get; set; }
}
please help me to rectify view, viewmodel and model class code. thanks
Add a viewmodel for Hobby:
public class HobbyViewModel
{
public int ID { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
Modify your StudentListViewModel as following:
public class StudentListViewModel
{
public IList<Student> Students { get; set; }
public List<Country> Country { get; set; }
public IList<HobbyViewModel> Hobbies { get; set; }
public StudentListViewModel()
{
Students = new List<Student>
{
new Student{ID=1,Name="Keith",CountryID=0,Hobby=0},
new Student{ID=2,Name="Paul",CountryID=2,Hobby=0},
new Student{ID=3,Name="Sam",CountryID=3,Hobby=0}
};
Country = new List<Country>
{
new Country{ID=1,Name="India"},
new Country{ID=2,Name="UK"},
new Country{ID=3,Name="USA"}
};
Hobbies = new List<HobbyViewModel>
{
new HobbyViewModel{ID=1,Name="Football"},
new HobbyViewModel{ID=2,Name="Hocky"},
new HobbyViewModel{ID=3,Name="Cricket"}
};
}
Replace the foreach in the view as following:
#for (var i = 0; i < Model.Hobbies.Count; i++)
{
<div class="checkbox">
#Html.HiddenFor(m => m.Hobbies[i].ID)
#Html.CheckBoxFor(m => m.Hobbies[i].Checked)
#Html.LabelFor(m => m.Hobbies[i].Checked, Model.Hobbies[i].Name)
</div>
}

Dropdownlist in MVC 5

I want to display multiple DropDownList MVC5. I have corresponding classes for the same. Kindly advise for the same. I am totally new to MVC.Value (SysId) needs to stored in database and description will be displayed in page. There are 4 dropdownlists in web page. All classes have same properties.
Kindly help for the same ..
public ActionResult Registration()
{
RegistrationClass obj = new RegistrationClass();
obj = obj.getAllDropdown();
return View(obj);
}
public class RegistrationClass
{
[Required(ErrorMessage = "Please enter Name")]
[StringLength(50, ErrorMessage = "Name can not be more than 50 characters ")]
[DisplayName("Name")]
public string name { get; set; }
[Required(ErrorMessage = "Please select Gender")]
[DisplayName("Gender")]
public string gender { get; set; }
[Required(ErrorMessage = "Please enter Date of Birth")]
[DisplayName("Date of Birth")]
[DataType(DataType.Date,ErrorMessage = "Invalid Date ")]
public DateTime dob { get; set; }
[DisplayName("Caste")]
public List<Caste> lcaste { get; set; }
public int cast_id { get; set; }
public RegistrationClass getAllDropdown()
{
RegistrationClass obj = new RegistrationClass();
Connection cobj = new Connection();
string strConn = cobj.getConnectionString();
SqlConnection con = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand("proc_get_preference_dropdown", con);
SqlDataAdapter ada = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
ada.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count;i++ )
{
if (ds.Tables[0].Rows[i]["code"].ToString() == "04") // Set Caste Preference
{
lcaste = new List<Caste>();
Caste obj1 = new Caste();
obj1.decription = ds.Tables[0].Rows[i]["description"].ToString();
obj1.sysId = Convert.ToInt32(ds.Tables[0].Rows[i]["id"]);
//obj1.isChecked = "N";
lcaste.Add(obj1);
obj.lcaste = lcaste;
continue;
}
}
}
return obj;
}
public class Caste
{
public int sysId { get; set; }
public string decription { get; set; }
public string isChecked { get; set; }
}
}
#model Matrimony.Models.RegistrationClass
<tr>
<td>
#Html.LabelFor(model => model.subcaste)
</td>
<td>
#Html.DropDownListFor(model => model.cast_id, new SelectList(Model.lcaste))
</td>
</tr>
Finally I resolved this by adding simple option tags.
<td>
<select name="cast_id">
<option value="0">--Select--</option>
#for (int i = 0; i < Model.lcaste.Count; i++)
{
<option value=#Model.lcaste[i].sysId>#Model.lcaste[i].decription</option>
}
</select>
</td>
The name property of select will get the selected item's value in post method. Accordingly we can handle it in controller. I also added property in my model class to store value as
public int cast_id { get; set; }
public List<Caste> lcaste { get; set; }

dynamically create textbox and save data MVC

I am new to MVC. I want to dynamically create textboxes upon user click.
<script>
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for(var i=0; i<colCount; i++) {
var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[0].cells[i].innerHTML;
switch(newcell.childNodes[0].type) {
case "text":
newcell.childNodes[0].value = "";
break;
case "checkbox":
newcell.childNodes[0].checked = false;
break;
case "select":
newcell.childNodes[0].selectedIndex = 0;
clear_attrib();
break;
}
}
else {
alert("Cannot add another row.");
}
}
function deleteRow(tableID) {
try {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if(null != chkbox && true == chkbox.checked) {
if(rowCount <= 1) {
alert("Cannot delete all the rows.");
break;
}
table.deleteRow(i);
rowCount--;
i--;
}
}
}catch(e) {
alert(e);
}
}
and the Razor
<table class="table" id="AddSchedule">
<tr>
<td><input type="checkbox" name="chk[]" class="checkbox_style" /></td>
<td>#Html.EditorFor(model => model.Schedule, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Schedule, "", new { #class = "text-danger" })
</td>
<td>#Html.EditorFor(model => model.Room, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Room, "", new { #class = "text-danger" })
</td>
<td>#Html.EditorFor(model => model.Subject, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Subject, "", new { #class = "text-danger" })
</td>
</tr>
the adding and removing of textboxes is OK. But I don't know how to save the data in the database. This is my controller
public ActionResult Create(EmployeeViewModel employeeViewModel)
{
if (ModelState.IsValid)
{
var emp = db.Employee.Create();
emp.ID = employeeViewModel.ID;
emp.LastName = employeeViewModel.LastName;
emp.FirstName = employeeViewModel.FirstName;
db.Employee.Add(emp);
var sched = db.FacultySchedule.Create();
sched.Schedule = employeeViewModel.Schedule;
sched.Room = employeeViewModel.Room;
sched.Subject = employeeViewModel.Subject;
db.FacultySchedule.Add(sched);
db.SaveChanges();
}
I tried using foreach but it still save only the first value, so i removed it... I think I'm missing something in the mark-up... like adding [] to make it an array just like in PHP. And I don't know how to fix it in the controller.
How can I fix the mark-up and the loop for in the controller for saving? Thanks.
Edit
this is the viewmodel
public class EmployeeViewModel
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Schedule { get; set; }
public string Room { get; set; }
public string Subject { get; set; }
public virtual IEnumerable<FacultySchedule> FacultySchedule { get; set; }
}
and these are the domain model
public partial class Employee
{
public Employee()
{
FacultySchedule = new HashSet<FacultySchedule>();
}
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public virtual ICollection<FacultySchedule> FacultySchedule { get; set; }
}
public partial class FacultySchedule
{
public FacultySchedule()
{
Substitution = new HashSet<Substitution>();
}
public int ID { get; set; }
public int EmployeeID { get; set; }
public string Schedule { get; set; }
public string Room { get; set; }
public string Subject { get; set; }
public virtual Employee Employee { get; set; }
}

MVC 5 Ajax.BeginForm POST does not bind to model in conroller

Sorry for the amount of code here but it's the best way to explain what;s happening.
I gave this code in my MVC 5 partial view:
#model Hide.MVC.MFC.Models.RequestDataModel
using (Ajax.BeginForm("RequestSetCanceledState", "Home", null,
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "request-info",
OnBegin = "AjaxAbsoluteLoaderOn",
OnComplete = "AjaxAbsoluteLoaderOff"
}, new { id = "formCancel" }))
{
<input id="sbmtCancel" type="submit" value="Cancel" />
#Html.DropDownListFor(m => m.CancelReason, new SelectList(Model.CancelReasons, "Id", "Name", Model.CancelReason), String.Empty)
#Html.TextBoxFor(m => m.Reason)
#Html.HiddenFor(m => m.RequestId)
}
My controller action is as follows:
[HttpPost]
public PartialViewResult RequestSetCanceledState(RequestDataModel model)
{
...
return PartialView("....", model);
}
And my model is as follows:
public class RequestDataModel
{
public RequestDataModel() { }
public RequestDataModel(int requestId)
{
this.RequestId = requestId;
using (var service = new InnerServiceClient())
{
var request = service.GetRequest(requestId);
this.State = request.ServiceState;
if (request.PremiseInformationId.HasValue)
{
this.PremisInformation = service.GetExistingData(requestId) ?? new PremiseInformationBL();
}
}
}
public int RequestId { get; set; }
public int State { get; set; }
public PremiseInformationBL PremisInformation { get; set; }
public int? CancelReason { get; set; }
public string Reason { get; set; }
public List<ListItem> CancelReasons
{
get
{
using (var service = new DictionaryServiceClient())
{
return service.GetShortList(TypeDictionary.MFCCancelReason).ToList();
}
}
}
}
The code does post to the RequestSetCanceledState method, and browser send message
CancelReason=1&Reason=123&RequestId=48&X-Requested-With=XMLHttpRequest
but the model is always empty. Also, if I use a GET request, the model is not empty! I tried to remove PremisInformation and CancelReasons from the model, but it did not help. Can someone please tell me why this might be?

Resources