How fix not working ActionResult Update in NET Core? - asp.net-core

I'm learning about .NET Core and I'm using code from this tutorial. But my update sql is not working.
Here is the index view code:
public ActionResult Index(int? id)
{
ViewBag.Operation = id;
ViewBag.Name = db.Chars.ToList();
Chars Chars = db.Chars.Find(id);
return View(Chars);
}
As for now it work I see results from sql and here is the updated part:
public ActionResult Update(Chars Chars)
{
if (ModelState.IsValid)
{
db.Entry(Chars).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index", new { id = 0 });
}
Here is index.cshtml part:
#using (Html.BeginForm()
{
#foreach (var item in (IEnumerable<MVC__test_2.Chars>)ViewBag.Name)
{
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(modelItem => item.CharName, new { htmlAttributes = new { #class = "form-control" } })
#Html.HiddenFor(modelItem => item.CharID, new { id = item.CharID })
</div>
</div>
#Html.ActionLink("Index", "Index", new { id = item.CharID })
<input type="submit" value="Update" name="Update"
style=#((ViewBag.Operation != null && Convert.ToInt32(ViewBag.Operation) > 0) ? "display:block" : "display:none") />
}
}

According to the tutorial you provided , I made a demo to test and it updated the data well. The following is the working example , you could refer to and make the modification as per your need .
Model
public class Description
{
public int Id { get; set; }
public string Display { get; set; }
}
Controller
public IActionResult Index(int? id)
{
ViewBag.Operation = id;
ViewBag.Name = _context.Description.ToList();
Description description= _context.Description.Find(id);
return View(description);
}
public ActionResult Update(Description description)
{
if (ModelState.IsValid)
{
_context.Entry(description).State = EntityState.Modified;
_context.SaveChanges();
}
return RedirectToAction("Index", new { id = 0 });
}
Index.cshtml , you should hide the id of the modified data in the modification section.
#model WebApplication1.Models.Description
#using (Html.BeginForm("Update", "Home", FormMethod.Post))
{
#foreach (var item in (IEnumerable<WebApplication1.Models.Description >)ViewBag.Name)
{
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(modelItem => item.Display, new { htmlAttributes = new { #class = "form-control" } })
#Html.HiddenFor(modelItem => item.Id, new { id = item.Id })
</div>
</div>
#Html.ActionLink("Edit", "Index", new { id = item.Id })
}
// Create or Update data
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
<fieldset>
<legend> <b>Entry Screen</b></legend>
<div class="form-group">
#Html.LabelFor(model => model.Display, new { #class = "control-label col-md-2" })
#Html.HiddenFor(model => model.Id)
<div class="col-md-10">
#Html.EditorFor(model => model.Display)
#Html.ValidationMessageFor(model => model.Display)
</div>
</div>
<div class="form-group">
<p>
<input type="submit" value="Create" name="Create"
style=#((ViewBag.Operation != null && Convert.ToInt32(ViewBag.Operation) > 0) ? "display:none" : "display:block") />
<input type="submit" value="Update" name="Update"
style=#((ViewBag.Operation != null && Convert.ToInt32(ViewBag.Operation) > 0) ? "display:block" : "display:none") />
</p>
</div>
</fieldset>
</div>
}

Related

mvc model fileupadload does not send model data

I have a mvc 5 asp.net file upload that upload pictures and create path for them.
File uploaded successfully, but model data does comes in null.
This is my model:
[Table("Slider")]
public partial class Slider
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Slider()
{
Slider1 = new HashSet<Slider>();
}
public int ID { get; set; }
public string Path { get; set; }
public int? Slider_ID { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Slider> Slider1 { get; set; }
}
This is Controller part:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Path")] Slider slider, List<HttpPostedFileBase> FileContent)
{
if (ModelState.IsValid)
{
byte[] imageData = null;
if (Request.Files.Count > 0)
{
HttpPostedFileBase poImgFile = Request.Files["Path"];
using (var binary = new BinaryReader(poImgFile.InputStream))
{
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
string picturePath = string.Format(Server.MapPath("~/content/slider/{0}.jpg"), slider.ID);
CreateDirectory(picturePath);
using (FileStream writer = new FileStream(picturePath, FileMode.Create))
{
writer.Write(imageData, 0, imageData.Length);
}
db.Sliders.Add(slider);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(slider);
}
And this is the view:
#using (Html.BeginForm("Create", "Sliders", FormMethod.Post, new { #class = "form-horizontal", role = "form", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="col-12 form-group">
<div class="row">
#Html.LabelFor(model => model.Path, "Picture", htmlAttributes: new { #class = "control-label col-12 col-md-2" })
<div class="col-12 col-md-10">
<input type="file" name="Path" id="fileUpload" accept=".png,.jpg,.jpeg,.gif" />
#Html.ValidationMessageFor(model => model.Path, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-12 text-left">
<input type="submit" value="create" class="btn btn-success" /> | #Html.ActionLink("back to list", "Index", null, new { #class = "btn btn-primary" })
</div>
</div>
</div>
}
When I check my database I see that Path is :
System.Web.HttpPostedFileWrapper
and Slider_ID is null and Slider_ID1 is null too.
Any suggestions?
After searching my previous codes, I've found that, when saving changes to db in controller class, db.SaveChanges(); slider argument which had been sent to Create method, will get new ID.
I've added these 2 lines after if:
if (ModelState.IsValid)
{
db.Sliders.Add(slider);
db.SaveChanges();
and done my other business logic in lines after that.

ajax beginform mvc callback

I have a single page with multiple partials set up. I want to be able to validate and update each partial seperatly. The validation works BUT when I type in a correct value and press save the page goes to the partial view instead of staying on the single page. What am I doing wrong here?
This is my main page :
#for (var i = 0; i < 10; i++)
{
var idTest = "Test_" + i;
<div id="#idTest">
#Html.Action("Detail", new { id = i })
</div>
}
The partial is created like this:
#{
var idTest = "Test_" + Model.Id;
var ajaxOptions = new AjaxOptions
{
UpdateTargetId = #idTest,
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace
};}
#using (Ajax.BeginForm("Detail", ajaxOptions))
{ #Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Test</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Gemeente, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Gemeente, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Gemeente, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
This is the simple model:
public class Test
{
public int Id { get; set; }
[Required(ErrorMessage = "Gelieve een gemeente op te geven")]
public string Gemeente { get; set; }
}
These are the actions:
[HttpGet]
public ActionResult Detail(int id)
{
Models.Test model = new Models.Test();
model.Id = id;
return View(model);
}
[HttpPost]
public ActionResult Detail(Models.Test model)
{
if(ModelState.IsValid)
{
return PartialView(model);
}
return PartialView(model);
}
Add these lines to your view and also use #Html.Partial as shown below
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
so that your main view is
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
#for (var i = 0; i < 10; i++)
{
var idTest = "Test_" + i;
<div id="#idTest">
#Html.Partial("Detail", new Test { Id = i })}
</div>
}
Scripts would be for unobtrusive ajax so that your ajax button works and Html.Partial so that first time when you load your page in foreach only partial view is rendered (not the full view)

How to retrieve Posted file in create action of another entity

I am in trouble with a posted file related to an entity, I can see the posted file in the request, but if I add the httppostedfile as action parameter it will be null... what should I do to manage this case?
NewsArticle model:
public class NewsArticle
{
public string Title{get; set;}
public int ID{get; set;}
[AllowHtml]
public string Body { get; set; }
public Image Image { get; set; }
//other stuff
}
where the field Image is:
the related entity will be created in the newarticlecontroller
public class Image
{
public int ID { get; set; }
public string URL { get; set; }
public string Title { get; set; }
public string Subtitle { get; set; }
}
detail of view
#model GatorsWebSite.NewsArticle
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "NewsArticles", FormMethod.Post, new { enctype = "multipart/forma-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>NewsArticle</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Body, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.Body, new { htmlAttributes = new { #class = "form-control ckHolder" } })
#Html.ValidationMessageFor(model => model.Body, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SubTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SubTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SubTitle, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Image, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Image, new { type = "file" })
#Html.ValidationMessageFor(m => m.Image)
</div>
</div>
#*<div class="form-group">
#Html.LabelFor(model => model.AuthorID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.AuthorID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.AuthorID, "", new { #class = "text-danger" })
</div>
</div>*#
#*<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>*#
<div class="form-group">
#Html.LabelFor(model => model.Published, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Published)
#Html.ValidationMessageFor(model => model.Published, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/ckEditor")
<script type="text/javascript">
CKEDITOR.replace("#Html.IdFor(m => m.Body)", {});
</script>
}
Controller action:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,Body,SubTitle,Published,Image")]NewsArticle newsArticle )// here I don't know how to manage the posted file
{
if (ModelState.IsValid)
{
newsArticle.Date = DateTime.Now;
newsArticle.AuthorID = User.Identity.GetUserId();
newsArticle.Body = newsArticle.Body;
_repository.Add(newsArticle);
return RedirectToAction("Index");
}
return View(newsArticle);
}
Any help will be really appreciated
And what if you put input file in your form like:
<div class="form-group">
<label for="newsimage">Select news image:</label>
<div class="col-md-10">
<div class="checkbox">
<input id="newsimage" type="file" name="newsimage"/>
</div>
</div>
</div>
and post action will be:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,Body,SubTitle,Published,Image")]NewsArticle newsArticle )// here I don't know how to manage the posted file
{
if (ModelState.IsValid)
{
string ImageUrl="";
for (int i = 0; i < Request.Files.Count; i++)
{
if (Request.Files[i].FileName!="")
{
string UrlFile = Server.MapPath("~/newsimagefolderpath/") + FileName;
Request.Files[i].SaveAs(UrlFile);
ImageUrl = UrlFile;
}
}
newsArticle.Date = DateTime.Now;
newsArticle.URL = string.IsNullOrEmpty(ImageUrl) ? "defaultimagepath" : ImageUrl;
newsArticle.AuthorID = User.Identity.GetUserId();
newsArticle.Body = newsArticle.Body;
_repository.Add(newsArticle);
return RedirectToAction("Index");
}
return View(newsArticle);
}
Ok, I am new to MVC so obviously I have to pay the tax, btw this is what I have done to solve this problem:
I have created a ViewModel to host the aggregated data of the view:
public class NewsArticleViewModel
{
public string Title { get; set; }
public int ID { get; set; }
[AllowHtml]
public string Body { get; set; }
public string SubTitle { get; set; }
public string AuthorID { get; set; }
public DateTime Date { get; set; }
public bool Published { get; set; }
public HttpPostedFileBase ImageUpload { get; set; }
}
then I have changed the signature of the control action:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Title,Body,SubTitle,Published,ImageUpload")]GatorsWebSite.ViewModels.NewsArticleViewModel newsArticle)
then I have corrected a typo in the form declaration :)
#using (Html.BeginForm("Create", "NewsArticles", FormMethod.Post, new { enctype = "multipart/form-data" }))
...and then I have changed the view
#Html.LabelFor(model => model.ImageUpload, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.ImageUpload, new { type = "file" })
#Html.ValidationMessageFor(m => m.ImageUpload)
</div>
Result:

Can you tell how to make a update in DB, with fileupload (File is updated ok)?

Can you tell how to make a update in DB, using fileupload (File is updated ok) ?
I dont get any errors message, but the edit controller make a new row in DB, instead of updating the old row.
I have tried to remove insertOnsubmit, but only result is no update at all, in DB
I'am using LINQ to SQL MVC4
Table id - CompanyNameCon - PdfCon
Controller:
public ActionResult Edit(int id = 0)
{
DAT_SupplyCon SupplyCon = db.DAT_SupplyCons.Where(x => x.ID == id).FirstOrDefault();
if (SupplyCon == null)
{
return HttpNotFound();
}
return View(SupplyCon);
}
//
// POST: /Books/Edit/5
[HttpPost]
public ActionResult Edit(DAT_SupplyCon DAT_SupplyCon, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
// Delete old file
FileUpload.DeleteFile(DAT_SupplyCon.PdfCon);
// Upload our file
DAT_SupplyCon.PdfCon = FileUpload.UploadFile(file);
???? db.DAT_SupplyCons.InsertOnSubmit(DAT_SupplyCon);
db.SubmitChanges();
return RedirectToAction("Index");
}
return View(DAT_SupplyCon);
}
view
#model CFire2.Models.DAT_SupplyCon
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Html.BeginForm("Edit", "SupplyCon", FormMethod.Post, new { enctype = "multipart/form- data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>DAT_SupplyCon</legend>
<div class="editor-label">
#Html.LabelFor(model => model.SupplierCon)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SupplierCon)
#Html.ValidationMessageFor(model => model.SupplierCon)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CompanyNameCon)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CompanyNameCon)
#Html.ValidationMessageFor(model => model.CompanyNameCon)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PdfCon)
</div>
<div class="editor-field">
<input type="file" name="file" />
#Html.HiddenFor(model => model.PdfCon)
#Html.ValidationMessageFor(model => model.PdfCon)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Utils:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
namespace CFire2.Utils
{
public static class FileUpload
{
public static char DirSeparator =
System.IO.Path.DirectorySeparatorChar;
public static string FilesPath = "Content" +
DirSeparator + "Uploads" + DirSeparator;
public static string UploadFile(HttpPostedFileBase file)
{
if (null == file) return "";
if (!(file.ContentLength > 0)) return "";
string fileName = file.FileName;
string fileExt = Path.GetExtension(file.FileName);
if (null == fileExt) return "";
if (!Directory.Exists(FilesPath))
{
Directory.CreateDirectory(FilesPath);
}
var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/SupplyCon"),fileName);
file.SaveAs(Path);
return fileName;
}
public static void DeleteFile(string fileName)
{
if (fileName.Length == 0) return;
var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/SupplyCon"), fileName);
if (File.Exists(Path.GetFullPath(path)))
{
File.Delete(Path.GetFullPath(path));
}
}
}
}
Add a hidden field for your primary key property to your form.
#Html.HiddenFor(model => model.ID)
Otherwise it'll be treated as a new record since no primary key is posted.
InsertOnSubmit method work on the basis of primary key .
if primary key value is not exists in DB it will create a new record otherwise it will update that record .
In your case you can use hidden field to store the primary key id into the model .
#Html.HiddenFor(model => model.PrimaryKeyID)

ListBoxFor is not fully updating the viewmodel on submit

I have been able to create viewmodel like this (please ignore that it includes another viewmodel, that will be fixed after I solve my current problem :) ):
public class UserViewModel
{
#region Variables
private SecUserViewModel user;
private string[] assignedRolesIds;
private List<SecRoleViewModel> availableRoles;
#endregion
#region Properties
public SecUserViewModel User
{
get { return this.user; }
set { this.user = value; }
}
public string Guid
{
get { return this.user.Guid.ToString(); }
set { this.user.Guid = value; }
}
public string UserName
{
get { return this.user.UserName; }
set { this.user.UserName = value; }
}
public string Email
{
get { return this.user.Email; }
set { this.user.Email = value; }
}
public byte[] AuthDigest
{
get { return this.user.AuthDigest; }
set { this.user.AuthDigest = value; }
}
public bool IsUsingTempPasswd
{
get { return this.user.IsUsingTempPasswd; }
set { this.user.IsUsingTempPasswd = value; }
}
public DateTime? LastLogin
{
get { return this.user.LastLogin; }
set { this.user.LastLogin = value; }
}
public DateTime? PasswordChanged
{
get { return this.user.PasswordChanged; }
set { this.user.PasswordChanged = value; }
}
public string[] AssignedRolesIds
{
get { return this.assignedRolesIds; }
set { this.assignedRolesIds = value; }
}
public List<SecRoleViewModel> AvailableRoles
{
get { return this.availableRoles; }
set { this.availableRoles = value; }
}
#endregion
#region Constructor
public UserViewModel()
{
User = new SecUserViewModel();
AssignedRolesIds = null;
AvailableRoles = new List<SecRoleViewModel>(0);
}
public UserViewModel(SecUserViewModel secUser, List<SecRoleViewModel> roleList, List<SecRoleViewModel> availableList)
{
User = secUser;
AssignedRolesIds = roleList.Select(r => r.Role.Guid.ToString()).ToArray();
AvailableRoles = availableList;
}
#endregion
}
My controller has an edit action. On "GET" I pass viewmodel and it is displayed properly including the multiselect list and preselected values. But when I "POST" the "Edit", UserViewModel that is passed back has "AssignedRolesIds" and "AvailableRoles" Empty, although everything else is filled. When I check FormCollection object, there are "AssignedRolesIds" present as a key.
My view looks like this:
#model DocuLive.ViewModels.UserViewModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_AdminPage.cshtml";
}
<h2>Edit</h2>
<div class="error-message">#TempData["Fail"]</div>
<div class="success-message">#TempData["Success"]</div>
#using (Html.BeginForm("Edit", "User", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>SecUser</legend>
<div class="editor-label">
#Html.LabelFor(model => model.User.Guid)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.User.Guid)
#Html.HiddenFor(model => model.User.Guid)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.UserName)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.User.UserName)
#Html.HiddenFor(model => model.User.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.Email)
#Html.ValidationMessageFor(model => model.User.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.IsUsingTempPasswd)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.IsUsingTempPasswd)
#Html.ValidationMessageFor(model => model.User.IsUsingTempPasswd)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.LastLogin)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.User.LastLogin)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.PasswordChanged)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.User.PasswordChanged)
</div>
<div class="hidden-field">
#Html.HiddenFor(model => model.User.AuthDigest)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssignedRolesIds)
</div>
<div class="editor-field">
#Html.ListBoxFor(x => x.AssignedRolesIds, new MultiSelectList(Model.AvailableRoles, "Guid", "RoleName"), new { Multiple = "multiple", #class = "multi-select-list" })
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Users")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Can anyone advise why only values related to ListBoxFor are not passed back (there is a null value)?
Thanks in advance
It seems that the problem is binding the string array values to string id value of complex object (in my case Role) - but I figured out a way around it eventually. The trick is to have this signature of the method:
[HttpPost]
public ActionResult Edit(UserViewModel user, string [] assignedRolesIds)
And then you have this in view:
#Html.ListBox("AssignedRolesIds",new MultiSelectList(Model.AvailableRoles, "Guid", "RoleName"),new { Multiple = "multiple", #class = "multi-select-list"})
With this solution, you have to reassign "assignedRolesIds" back to "AssignedRolesIds" property on UserViewModel, but that is only two lines (including check that the array is not emppty or null).