So, I have this Property class that is defined by ID Name and DataType.
DataType is already populated with static values, and is being used as a drop down list.
Now when a user picks certain value from the list, List value to be precise, application opens additional textbox and button, for populating that list.
Models go like this.
Property model
public class Property
{
public int ID {get; set;}
public string Name {get; set;}
public int DTypeID {get; set;}
public virtual DType DTypes {get; set;}
}
List model
public class DList
{
public int ID {get; set;}
public int PropertyID {get; set;}
public string ListValue {get; set;}
}
And this is what I've done so far.
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<div class="labels tableRow">
<div class="editor-label tableCell">
<p>
Name
</p>
<p>
Data Type
</p>
</div>
<div class="editor-field tableCell">
<p>
#Html.TextBoxFor(model => model.Name, new { #class = "textEntry" })
#Html.ValidationMessageFor(model => model.Name)
</p>
<p>
#Html.DropDownList("DTypeID", (SelectList)ViewBag.DTypeID, new { #class = "dropdown", #onchange = "DropDownChange()"})
#Html.ValidationMessageFor(model => model.DTypeID)
</p>
</div>
</div>
<div id="StaticListUI" class="invis">
<div class="labels tableRow">
<div class="editor-label tableCell">
<p>
#*here goes list*#
</p>
</div>
<div class="editor-field tableCell">
<p>
#*here goes textbox*#
#Html.TextBox("textboxList")
</p>
<p>
#*here goes button*#
<button name="button" value="add">Add</button>
</p>
</div>
</div>
</div>
<p class="labels">
#*<input type="submit" value="Create" />*#
<button name="button" value="create">Create</button> |
<input type="button" value="Back" onClick='javascript:location.href = "#Url.Action("Index", "Property")";' />
</p>
</fieldset>
}
So in order to capture which button is clicked I did this for my controller.
[HttpPost]
public ActionResult Create(string button, string textboxList, Property property)
{
if (button == "add")
{
var lastProperty = db.Properties.OrderByDescending(p => p.PropertyID).FirstOrDefault();
int propID;
if (lastProperty == null)
{
propID = 1;
}
else
{
propID = 1 + lastProperty.PropertyID;
}
DList dList = new DList();
dList.PropertyID = propID;
dList.ListValue = textboxList;
db.DLists.Add(dList);
return View(property);
}
string projectID = System.Web.HttpContext.Current.Session["_SelectedProjectID"].ToString();
int projID = Convert.ToInt32(projectID);
property.ProjectID = projID;
property.DateCreated = DateTime.Now;
property.DateEdited = DateTime.Now;
if (ModelState.IsValid)
{
db.Properties.Add(property);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DTypeID = new SelectList(db.DType, "ID", "Name", property.DTypeID);
return View(property);
}
And the problem is that when I click Add button, it still sends a check for ModelState.IsValid, which shouldn't. What have I done wrong, or have I done anything right :(
Note: Everything else basically works.
EDIT
So I've altered the controller to accept parameters from button clicked differently. But still something is missing...
[ActionName("Create")]
[AcceptVerbs(HttpVerbs.Post)]
[AcceptParameter(Name = "button", Value = "add")]
public ActionResult Create_Add(string textboxList)
{
var lastProperty = db.Properties.OrderByDescending(p => p.PropertyID).FirstOrDefault();
int propID;
if (lastProperty == null)
{
propID = 1;
}
else
{
propID = 1 + lastProperty.PropertyID;
}
DList dList = new DList();
dList.PropertyID = propID;
dList.ListValue = textboxList;
db.DLists.Add(dList);
db.SaveChanges();
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
[AcceptParameter(Name="button", Value="create")]
public ActionResult Create(Property property)
{
string projectID = System.Web.HttpContext.Current.Session["_SelectedProjectID"].ToString();
int projID = Convert.ToInt32(projectID);
property.ProjectID = projID;
property.DateCreated = DateTime.Now;
property.DateEdited = DateTime.Now;
if (ModelState.IsValid)
{
db.Properties.Add(property);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DTypeID = new SelectList(db.DType, "ID", "Name", property.DTypeID);
return View(property);
}
public class AcceptParameterAttribute : ActionMethodSelectorAttribute
{
public string Name { get; set; }
public string Value { get; set; }
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
var req = controllerContext.RequestContext.HttpContext.Request;
return req.Form[this.Name] == this.Value;
}
}
You have db.DLists.Add(dList); but do don't save it in the database, you just return the view. You could put db.Configuration.ValidateOnSaveEnabled = false; above the db.DLists.Add(dList); and see if that works, however I think it should look like this:
db.Configuration.ValidateOnSaveEnabled = false;
db.DLists.Add(dList);
db.SaveChanges();
return View(property);
You may want to turn the Validate On Save back on before the return.
Update
Perhaps you could try this:
#{
var textBoxData = form.find('input[name="textboxList"]').val();
}
<input type="button" value="Add" title="Add" onclick="location.href='#Url.Action("Create_Add", "Controller", new { textboxList = textBoxData })'" />
Related
I have httpost activate method which should store the user record(from poll user options model) in database. Activate method display pop-up for user and he chooses one of the choices and submit it. The method purpose is to create record from Poll user options model through the Poll view model.
[HttpPost]
public ActionResult Activate(PollOptionsVM pum)
{
User user = UserService.GetCurrent();
if (ModelState.IsValid)
{
Poll_User_Options model = new Poll_User_Options()
{
poll_id = pum.PollID,
user_id = user.ID,
option_id = pum.OptionID
};
PollUserOptionsService.Create(model); //model
//return RedirectToAction("Index1");
}
return View();
}
And activate view from poll view model. The model state is invalid and record is not created always because pum.PollID and pum.OptionID returns 0 from view. How to create record when user submits credentials
#model test.ViewModels.PollVM
#if (ViewBag.ViewPopup)
{
<div id="PollModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm("Activate", "Poll", FormMethod.Post))
{
<h2>Index</h2>
<div class="container">
#Html.HiddenFor(m => m.PollID)
<div class="form-group row">
<label for="polltitle" class="col-lg-2 col-md-2 col-sm-12 col-xs-12 col-form-label col-lg-offset-1 col-md-offset-1">
#Html.DisplayNameFor(m => m.Title)
<span class="text-danger">*</span>
</label>
<div class="col-lg-7 col-md-7 col-sm-12 col-xs-12">
#Html.TextBoxFor(m => m.Title, new { #id = "QuestionTextBody", #class = "form-control ckeditor", disabled = "disabled" })
#Html.ValidationMessageFor(m => m.Title, null, new { #class = "text-danger" })
</div>
</div>
<div class="form-group row">
<table id="myTable" class="order-list">
<thead>
#foreach (var item in Model.PollOptionList)
{
<tr>
<td class="col-sm-7">
#Html.TextBox("OptionTitle", item.Title, new { placeholder = "Enter text here", #class = "form-control", disabled = "disabled" })
#Html.RadioButton("OptionTitle", item.OptionID, new { #class = "custom-control-input"})
</td>
</tr>
}
</thead>
<tbody></tbody>
</table>
</div>
#*<button href="/Poll/Answer" type="submit" value="Submit">Save</button>*#
<button type="submit" value="Submit">Save</button>
</div>
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
}
Here is my PollVM
public class PollVM
{
public int PollID { get; set; }
[Display(Name = "Type")]
[Required]
public int Type { get; set; }
[Display(Name = "Status")]
[Required]
public int Status { get; set; }
[Display(Name = "Title")]
[Required]
public string Title { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateEdited { get; set; }
public List<PollOptionsVM> PollOptionList { get; set; }
public List<PollUserOptionsVM> PollUserOptionsList { get; set; } //added
public int IsSelected { get; set; } //added
public Poll ToModel(PollVM vm)
{
Poll model = new Poll();
model.id = vm.PollID;//added
model.type = vm.Type;
model.status = vm.Status;
model.title = vm.Title;
model.date_created = DateTime.Now;
model.date_edited = model.date_created;
if (vm.PollOptionList != null)
{
foreach(var item in vm.PollOptionList)
{
var option = new Poll_Options();
option.title = item.Title;
option.date_created = DateTime.Now;
option.date_edited = DateTime.Now;
model.Poll_Options.Add(option);
}
}
return model;
}
public Poll ToEditModel(PollVM vm, Poll model)
{
model.type = vm.Type;
model.status = vm.Status;
model.title = vm.Title;
model.date_created = DateTime.Now;
model.date_edited = DateTime.Now;
if(vm.PollOptionList != null)
{
foreach (var item in vm.PollOptionList)
{
var option = new Poll_Options();
option.title = item.Title;
option.date_created = DateTime.Now;
option.date_edited = DateTime.Now;
model.Poll_Options.Add(option);
}
}
return model;
}
public PollVM ToViewModel(Poll model)
{
PollVM ViewModel = new PollVM()
{
PollID = model.id,
Type = model.type,
Status = model.status,
Title = model.title,
DateCreated = model.date_created,
DateEdited = model.date_edited,
PollOptionList = new List<PollOptionsVM>()
};
if (model.Poll_Options.Count != 0)
{
foreach (var option in model.Poll_Options)
{
var optionVM = new PollOptionsVM();
optionVM.OptionID = option.id;
optionVM.PollID = option.poll_id;
optionVM.Title = option.title;
optionVM.DateCreated = DateTime.Now;
optionVM.DateEdited = DateTime.Now;
ViewModel.PollOptionList.Add(optionVM);
}
}
return ViewModel;
}
public List<PollVM> ToViewModelList(List<Poll> polls)
{
List<PollVM> pollList = new List<PollVM>();
foreach(var item in polls)
{
pollList.Add(ToViewModel(item));
}
return pollList;
}
}
get Activate method
public ActionResult Activate()
{
PollVM vm = new PollVM();
Poll poll = PollService.GetPollByStatusActive();
PollVM pvm = new PollVM();
bool b = false;
if (poll != null)
{
pvm = vm.ToViewModel(poll);
b = true;
}
ViewBag.ViewPopup = b;
return PartialView(pvm);
}
I changed your code a bit. Follow these steps. this code work for me. Replace the SetPoll() method with your own data
Change view to this
#foreach (var item in Model.PollOptionList)
{
<tr>
<td class="col-sm-7">
#Html.TextBox("OptionTitle", item.Title, new { placeholder = "Enter text here", #class = "form-control", disabled = "disabled" })
#Html.RadioButton("OptionID", item.OptionID, new { #class = "custom-control-input"})
</td>
</tr>
}
change action to this
public ActionResult Activate()
{
Poll poll = SetPoll();
PollVM pvm = new PollVM();
bool b = false;
if (poll != null)
{
pvm = pvm.ToViewModel(poll);
b = true;
}
ViewBag.ViewPopup = b;
return View(pvm);
}
[HttpPost]
public ActionResult Activate(PollVM pollVM,int OptionID)
{
User user = UserService.GetCurrent();
Poll poll = SetPoll();
bool b = false;
if (poll != null)
{
pollVM = pollVM.ToViewModel(poll);
b = true;
}
Poll_User_Options model = new Poll_User_Options()
{
poll_id = pollVM.PollID,
user_id = user.ID,
option_id = OptionID
};
PollUserOptionsService.Create(model); //model
ViewBag.ViewPopup = b;
return View(pollVM);
}
public Poll SetPoll()
{
Poll poll = new Poll()
{
id = 1,
type = 1,
date_created = DateTime.Now,
title = "poll1",
status = 2,
Poll_Options = new List<Poll_Options>()
{
new Poll_Options(){id=1,title="option1",poll_id=1,date_created=DateTime.Now},
new Poll_Options(){id=2,title="option2",poll_id=1,date_created=DateTime.Now},
new Poll_Options(){id=3,title="option3",poll_id=1,date_created=DateTime.Now},
}
};
return poll;
}
I'm beginner in asp.net mvc.
I have a product model and I want implement user comments for any product.
I want to show comments as tree for each level.
I use a recursive method in my view to show comments and reply comment but
it cant show reply comments in third level .
The first level terms when replyId is empty displayed. Reply to first comment are displayed first. But the answer of Previous reply does not show in the third level.
Please help me. Thank you so much.
This is my model
namespace Mvc_Shop.Models
{
public class Comment
{
public Comment()
{
this.Children = new HashSet<Comment>();
}
public int Id { set; get; }
public string Body { set; get; }
public System.DateTime CommentDate { get; set; }
public int? ReplyId { get; set; }
public ICollection<Comment> Children { get; set; }
public virtual Comment Reply { set; get; }
public string User_Id { get; set; }
[ForeignKey("User_Id")]
public virtual User User { get; set; }
public int Product_Id { get; set; }
[ForeignKey("Product_Id")]
public virtual Product Product { get; set; }
}
}
This is my view
#helper TreeView(IEnumerable<Mvc_Shop.Models.Comment> Comments)
{
foreach (var item in Comments)
{
<div class="media">
<div class="media-body" id="Comment_#(item.Id)" style="padding: 3px;width: 100%;">
<h4 class="media-heading">
#item.User.UserName
<label class="badge pull-left" style="font-weight: normal">#item.CommentDate.ToString("dddd, dd MMMM yyyy - HH:mm")</label>
</h4>
<div class="clearfix">
#item.Body
</div>
<fieldset id="reply-cmnt-form_#(item.Id)" class="spr-form-review" style="display:none">
<div class="spr-form-review-body">
#Html.LabelFor(model => model.Comment.Body, new { #class = "spr-form-label" })
#Html.TextAreaFor(model => model.Comment.Body, new { #class = "spr-form-input spr-form-input-text", id = "commentbody" + #item.Id })
#Html.ValidationMessageFor(model => model.Comment.Body)
</div>
</fieldset>
<a id="btn-hide-div_#(item.Id)" class="btn btn-xs pull-left btn-primary" style="clear: both; display:none" onclick="opencmntdiv(#item.Id);"> بستن</a>
<a id="btn-send-div_#(item.Id)" class="btn btn-xs pull-left btn-primary" style="clear: both;float:right;display:none" onclick="ReplyComment(#item.Id);"> ارسال پاسخ</a>
<a id="btn-show-div_#(item.Id)" class="btn btn-xs pull-left btn-primary" style="clear: both" onclick="opencmntdiv(#item.Id);"> پاسخ</a>
</div>
</div>
<hr class="clearfix" />
if (item.Children.Any())
{
#TreeView(item.Children)
}
}
}
#TreeView(Model.Comments)
and this is my action
public ActionResult ShowProducts(string ProductName)
{
_dbContext = HttpContext.GetOwinContext().Get<ShopContext>();
var model = new UserCommentViewModel();
if (string.IsNullOrEmpty(ProductName))
{
return RedirectToAction("Index");
}
else
{
model.Products = blproduct.Where(p => p.Name.Trim() == ProductName.Trim()).ToList();
model.Comments = (from u1 in _dbContext.Users
join u2 in _dbContext.Comments
on u1.Id equals u2.User.Id
where u2.ReplyId == null
select new {
Id = u2.Id, Body = u2.Body, CommentDate = u2.CommentDate, User = u1,Children = u2.Children
}).ToList().Select(x => new Comment
{
Id = x.Id, Body = x.Body, CommentDate = x.CommentDate, User = x.User,Children = x.Children
}).ToList();
if (model != null)
{
return View(model);
}
else
{
return RedirectToAction("Index");
}
}
}
Thanks a lot.
It's time to ask the internet. I'm a student and really new to MVC + coding in general, but I can't for the life of me figure out why this isn't working. Probably something really obvious. :/
I have a View (AddMemberToGroup) that is strongly-typed to a viewmodel (PersonGroupingViewModel). What am I trying to do is add a Person to a Group, with the user selecting a group from a dropdown list in the View.
Viewmodel:
public class PersonGroupingViewModel
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set;}
public List<Group> Memberships { get; set; }
public SelectList AllGroups { get; set; }
public int SelectedGroupId { get; set; }
}
Controller:
//GET People/AddToGroup
public ActionResult AddMemberToGroup(int? PersonId)
{
if (PersonId == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Person person = db.People.Find(PersonId);
if (person == null)
{
return HttpNotFound();
}
SelectList allthegroups = new SelectList(db.Groups, "GroupId", "Name");
PersonGroupingViewModel viewmodel = new PersonGroupingViewModel();
viewmodel.PersonId = person.PersonId;
viewmodel.FirstName = person.FirstName;
viewmodel.LastName = person.LastName;
viewmodel.AllGroups = allthegroups;
//viewmodel.Memberships cannot be empty
if (person.Memberships == null)
{
viewmodel.Memberships = new List<Group>();
}
else
{
viewmodel.Memberships = person.Memberships.ToList();
}
return View(viewmodel);
}
//POST: People/AddToGroup
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddMemberToGroup(PersonGroupingViewModel vm)
{
SelectList allthegroups = new SelectList(db.Groups, "GroupId", "Name");
vm.AllGroups = allthegroups;
int PersonId = vm.PersonId;
int GroupId = vm.SelectedGroupId;
Person person = db.People.Find(PersonId);
Group group = db.Groups.Find(GroupId);
group.Members.Add(person);
db.SaveChanges();
return View(vm);
}
View form (strongly-typed to PersonGroupingViewModel):
Add Member To Group
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div>
<h4>Groups #Html.DisplayFor(model => model.FirstName) is already in:</h4>
<ul>
#foreach (var group in Model.Memberships)
{
<li>#Html.DisplayFor(modelItem => group.Name)</li>
}
</ul>
</div>
<div class="form-horizontal">
<h4>Add #Html.DisplayFor(model => model.FirstName) #Html.DisplayFor(model => model.LastName) To Group:</h4>
#Html.HiddenFor(model => model.PersonId)
<div class="form-group">
<label>Group: </label>
#Html.DropDownListFor(m => m.SelectedGroupId, Model.AllGroups, String.Empty)
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Add To Group" class="btn btn-default" />
</div>
</div>
</div>
}
When I click 'submit' in the browser I get back a URL:
localhost:54696/People/AddMemberToGroup?PersonId=1
Along with exception "Object reference not set to an instance of an object" on the line Group group = db.Groups.Find(GroupId); in the controller.
Is the viewmodel coming back empty or not at all? I am not sure what is going on and would appreciate someone attempting explaining it in small words. I've done a lot of Googling and tried several suggestions from that but in the end I feel as though I'm going in circles.
Solved it...
group.Members was null so group.Members.Add(person) didn't work. Wrote in an if/else statement to instantiate a new member list if the list is null, and it works fine:
if (group.Members == null)
{
group.Members = new List<Person>();
group.Members.Add(person);
}
else {
group.Members.Add(person);
}
I have a page to create objects, and in this I have a DropDownList. If I select an item from the list my page will save correctly, however if I don't select an item it looks like it fails on a postback as the objects will be null.
What I want is to try and validate whether the user has selected an item (default is "Please Select...").
I have code that will check and see in the controller if the item is null, but it's how do I then display a message? Keeping all other details if they exist.
public ActionResult Create(int objectId = 0)
{
var resultModel = new MyObjectModel();
resultModel.AllObjects = new SelectList(_system.GetAllObjects(objectId));
// GetAllObjects juts returns a list of items for the drop down.
return View(resultModel);
}
[HttpPost]
public ActionResult Create(int? objectId, FormCollection collection)
{
try
{
int objectIdNotNull = 0;
if (objectId > 1)
{
objectIdNotNull = (int) objectId;
}
string objectName = collection["Name"];
int objectTypeSelectedResult = 1;
int.TryParse(collection["dllList"], out objectTypeSelectedResult);
if (!Convert.ToBoolean(objectTypeSelectedResult))
{
// So here I have discovered nothing has been selected, and I want to alert the user
return RedirectToAction("Create",
new {ObjectId = objectIdNotNull, error = "Please select an Object Type"});
}
....
return RedirectToAction(...)
}
catch
{
return View();
}
}
The above code just goes to the Create page but doesn't display an error. In my View for Create I have the following line which I assumed would display any errors:
#ViewData["error"]
Additional code
Model:
using System.Collections.Generic;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
namespace MyNameSpace
{
public class MyObjectModel
{
[Required(ErrorMessage = "Please select an Object Type")]
public SelectList AllObjects { get; set; } // I populate the drop down with this list
}
}
View:
#model MyNameSpace.MyObjectModel
#{
ViewBag.Title = "Create";
}
<h2>Create </h2>
<p class="text-error">#ViewData["Message"]</p>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"> </script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.MyObject.Name)
</div>
<div class="editor-field">
#Html.TextBoxFor(model=>model.MyObjectType.Name, new {style="width: 750px"})
#Html.ValidationMessageFor(model => model.MyObjectType.Name)
</div>
<div>
<label for="ddlList">Choose Type</label>
#if (#Model != null)
{
#Html.DropDownList("ddlList", Model.AllObjects, "Please Select...")
#Html.ValidationMessageFor(model => model.AllObjects, "An object must be selected", new { #class = "redText"})
}
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
You are validating the SelectList which is wrong
[Required(ErrorMessage = "An object must be selected")]
public SelectList AllObjects { get; set; }
Your Model should be
[Required(ErrorMessage = "Please select an Object Type")]
public int ObjectId { get; set; }
public string ObjectName { get; set; }
Your Controller(no need for form collection thats the whole point of MVC)
public ActionResult Create(int Id = 0)
{
MyObjectModel resultModel = new MyObjectModel();
var ObjectResultList = _system.GetAllObjects(Id);
var ObjectSelectList = new SelectList(ObjectResultList, "id", "Name");
ViewBag.ObjectList = ObjectSelectList;
return View(resultModel);
}
Your Post controller:
[HttpPost]
public ActionResult Create(MyObjectModel o)
{
try
{
if (ModelState.IsValid)
{
//It's valid , your code here!
return RedirectToAction("ObjectCreated", new { id = o.objectId });
}
else
{
var errors = ModelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new { x.Key, x.Value.Errors })
.ToArray();
}
}
}
catch (Exception ex)
{
Response.Write(ex.InnerException.Message);
}
//If we get here it means the model is not valid, We're in trouble
//then redisplay the view repopulate the dropdown
var ObjectResultList = _system.GetAllObjects(objectId);
var ObjectSelectList = new SelectList(ObjectResultList, "id", "value");
ViewBag.ObjectList = ObjectSelectList;
return View(o);
}
Your View should be strongly Typed
<div class="editor-label">
#Html.LabelFor(model => model.ObjectId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ObjectId,
(IEnumerable<SelectListItem>)ViewBag.ObjectList, "-- Select One Object --")
#Html.ValidationMessageFor(model => model.ObjectId)
</div>
I have some problem posting a form with 'complex type' model:
I have a Model:
public class CircleEditViewModel
{
[Key]
public int CircleId { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
public bool IsSystem { get; set; }
public class UserInCircle
{
public UserInCircle(User user)
{
this.UserId = user.UserId;
FullName = user.FullName;
}
public int UserId { get; set; }
public byte[] Picture { get; set; }
public string FullName { get; set; }
public bool isInCircle { get; set; }
}
public List<UserInCircle> Users { get; set; }
}
My first problem was that at post event, my Users where null.. so i followed a few posts on here (like MVC- Model Binding on a Complex Type) to use a for instead of a foreach,but since i did so, my form won't post anymore:
View:
#model Wims.Website.ViewModels.CircleEditViewModel
<script type="text/javascript">
$(document).ready(function () {
$.validator.unobtrusive.parse('form');
});
</script>
#using (Ajax.BeginForm(Html.ViewContext.RouteData.Values["Action"].ToString(), null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SaveDone(data)" }, new { id = "editform" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Circle</legend>
#Html.Label(DateTime.Now.ToString());
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</fieldset>
if (Model.Users != null)
{
for (int i = 0; i < Model.Users.Count; i++)
{
<div class="userDetail">
<div>
<div>
#Html.DisplayFor(model => Model.Users[i].isInCircle);
</div>
<div class="iconDiv">
#Html.Image("~/Content/Images/defaultUser.jpg", Model.Users[i].FullName, null);
</div>
<div>
#Html.TextBoxFor(model => Model.Users[i].FullName)
#Html.HiddenFor(model => Model.Users[i].UserId)
</div>
</div>
</div>
<div style="clear: both"></div>
}
}
#Html.GenerateSecureDataControls(model => model.CircleId)
<input type="submit" value="Save" />
}
My view is rendered as a partial loaded thru ajax (not sure it makes any difference here).
Any idea why it won't post? If i remove all the '[]' like 'Users[0].FullName' to Users0.FullName i will post, but of course it won't be bound.
Thanks for your help
Edit just in case needed: Action:
[HttpPost]
public ActionResult Edit(CircleEditViewModel circleData, FormCollection collection)
{
if (ModelState.IsValid)
{
using (var logic = new CircleLogic())
{
Circle circle = logic.GetCircleById(circleData.CircleId, WebMatrix.WebData.WebSecurity.CurrentUserId);
if (circle == null)
{
return HttpNotFound();
}
else
{
circle.Name = circleData.Name;
logic.UpdateCircle(circle, GetSelectedUser(collection));
}
return PartialView("_CircleAndUsers", GetData(logic, circle.CircleId));
}
}
return this.Json(new { success = false, viewdata = RenderRazorViewToString("_CircleAndUsers", circleData) });
}
Pablo Romeo was right, i added a default ctor and it worked.