how to create multiple textbox with a list of objects - asp.net-mvc

hi folks i have to create a share stuff page where i have a contentitem to share, the user who share it and the recipients of the ppl he wants to share it with, but i want to do it dynamic, this is my domain model
public class ShareContentItemModel : BaseModel
{
public ContentItem ContentItem { get; set; }
public User User { get; set;}
[Display(Name = "Recipients")]
public List<Recipient> Recipients { get { return new List<Recipient> { new Recipient { Name = "Recipient name here", Email = "Write Recipient Email here" } }; } }
[Required]
[Display(Name = "Nachricht")]
public string Message { get; set; }
}
public class Recipient{
[Display(Name = "Recipient Name:")]
public string Name { get; set;}
[Display(Name = "Recipient Email Address:")]
public string Email { get; set;}
}
and this is my view
#using (Html.BeginForm("Submit", "Contact", FormMethod.Post))
{
<p>Hi: #Html.DisplayTextFor(m=>m.User.Salutation) #Html.DisplayTextFor(m=>m.User.Firstname) #Html.DisplayTextFor(m=>m.User.Lastname)</p>
<table border="0" style="padding:5">
<tr>
<td class="editor-label">#Html.LabelFor(m => m.ContentItem.Title): </td>
<td class="editor-field">#Html.DisplayTextFor(m => m.ContentItem.Title)
<div>#Html.ValidationMessageFor(m => m.ContentItem.Title)</div>
</td>
</tr>
<tr>
<td class="editor-label">#Html.LabelFor(m => m.ContentItem.Description): </td>
<td class="editor-field">#Html.DisplayTextFor(m => m.ContentItem.Description)
<div>#Html.ValidationMessageFor(m => m.ContentItem.Title)</div>
</td>
</tr>
<tr><td colspan="2">Recipients:</td></tr>
#foreach (var item in #Model.Recipients)
{
<tr>
<td>#item.Name: #Html.TextBoxFor(/*Dont know what to put in here*/)</td>
<td>#item.Email: #Html.TextBoxFor(/*Dont know what to put in here*/) </td>
</tr>
}
<tr>
<td> <a class="small button" href="#">Add Recipient:</a> </td>
<td><input type="submit" class="button med primary" style="float: right;" value="ABSENDEN" /></td>
</tr>
</table>
}
as you can see in the //Dont know what to put in here
i cant use the item.name or item.email properties can you help me with this
p.d. the object is fine the cshtml is rendering fine, i just need to create this textboxes to start creating more recipients.
thank you very much

OK. So here is how you do it. You create an Editor template and use it.
Step 1) Create a folder called "EditorTemplates" in your View/yourViewFolderName
Step 2) Create a View called Receipent.cshtml
Add this code to that file
#model YourNameSpace.Models.Recipient
<p>
#Html.EditorFor(x=>x.Name) : #Html.TextBoxFor(x=>x.Name)
</p>
<p>
#Html.EditorFor(x=>x.Email) : #Html.TextBoxFor(x => x.Email)
</p>
Step 3) In your Main View, just call the editor template instead of the foreach loop code
#Html.EditorFor(x=>x.Recipients)
This should work fine. I tested with your models.
Keep your editor template name same as of your Property name which you want to show in a foreach. MVC will take care of the rest.

Related

MVC Form returns null model back to controller [duplicate]

This question already has answers here:
Submit a List from View to Controller
(2 answers)
Closed 5 years ago.
View has a list of items, each with a checkbox. Purpose of the form is to check the boxes then return the list to the db. I expect to see the PickList model in the ViewModel populated with the hidden seedid and the checkbox values, but the form always submits with the PickList as null.
#model Inventory.ViewModels.ExtractionViewModel
<div class="col-md-4">
<button class="btn btn-primary" type="submit" form="pick-list-form">Update Pick List</button>
</div>
#using (Html.BeginForm("UpdatePickList", "Extraction", FormMethod.Post, new { #id = "pick-list-form" }))
{
<table class="table">
<tr>
<th>
Seed Reference
</th>
<th>Extracted?</th>
</tr>
#foreach (var item in Model.PickList)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.ExtractionId)
#Html.HiddenFor(modelItem => item.SeedId)
#Html.DisplayFor(modelItem => item.SeedId)
</td>
<td>
#Html.CheckBoxFor(modelItem => item.IsExtracted)
</td>
</tr>
}
</table>
}
View Model
public class ExtractionViewModel
{
public ExtractionDTO Extraction{ get; set; }
public List<PickListDTO> PickList { get; set; }
}
Pick list model
public class PickListDTO
{
public int ExtractionId { get; set; }
public int SeedId { get; set; }
public bool IsExtracted { get; set; }
}
Using #Html.DisplayFormay cause the model to be sent back as NULL. You can use #Html.TextBoxFor.
And just to remind:
Use HiddenFor when you want to provide posted data that the user does not need to be aware of.
Use DisplayFor when you want to show records but not allow them to be editted.
Use TextBoxFor when you want to allow user input or allow the user to edit a field.
I hope it helps you!

Html.BeginForm call the right Action in Controller

There are a lot of topics related to this question but I still did't figured out what I'm doing wrong.
I have a database where I manage access of different users to folders. On my View the User can select Employees which should have access to certain folder. Then I want to pass the selected Employees to Controller, where the database will be updated.
My Problem is: The right Action in the Controller class didn't get invoked.(I have a breakpoint inside)
Here is the View
#model DataAccessManager.Models.EmployeeSelectionViewModel
#{
ViewBag.Title = "GiveAccessTo";
}
#using (Html.BeginForm("SubmitSelected", "FolderAccessController", FormMethod.Post, new { encType = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.fr_folder_uid_fk)
<div class="form-horizontal">
<input type="submit" value="Save" id="submit" class="btn btn-default" />
<table id="tableP">
<thead>
<tr>
<th>Selection</th>
<th>Second Name</th>
<th>First Name</th>
<th>Department</th>
</tr>
</thead>
<tbody id="people">
#Html.EditorFor(model => model.People)
</tbody>
</table>
</div>
</div>
</div>
}
Here is the Controller reduced to the minimum
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SubmitSelected(EmployeeSelectionViewModel model)
{
return View();
}
More Details: I am not sure what is causing the problem, so here some more details.
The view is strongly typed to EmployeeSelectionViewModel, it represets the table with all Employees as a List here is the the code:
public class EmployeeSelectionViewModel
{
public List<SelectEmployeeEditorViewModel> People { get; set; }
public EmployeeSelectionViewModel()
{
this.People = new List<SelectEmployeeEditorViewModel>();
}
public Int64 fr_folder_uid_fk { get; set; }
public IEnumerable<string> getSelectedIds()
{
// Return an Enumerable containing the Id's of the selected people:
return (from p in this.People where p.Selected select p.fr_mavnr_fk).ToList();
}
}
The SelectEmployeeEditorViewModel represents one row of the table with all Employees.
public class SelectEmployeeEditorViewModel
{
public bool Selected { get; set; }
public string fr_mavnr_fk { get; set; }
public string firstName { get; set; }
public string secondName { get; set; }
public string dpt { get; set; }
}
And it has a View which create the checkboxes for each Employee
#model DataAccessManager.Models.SelectEmployeeEditorViewModel
<tr>
<td style="text-align:center">
#Html.CheckBoxFor(model => model.Selected)
#Html.HiddenFor(model => model.fr_mavnr_fk)
</td>
<td>
#Html.DisplayFor(model => model.secondName)
</td>
<td>
#Html.DisplayFor(model => model.firstName)
</td>
<td>
#Html.DisplayFor(model => model.dpt)
</td>
</tr>
The /FolderAccessController/SubmitSelected URL is called in the browser when I press the Submit button, but as mentioned the Action isn't invoked.
EDIT: I get the HTTP 404 not found error after pressing the button
Try removing the "Controller" word from your Html.BeginForm() second parameter, it's not needed.
#using (Html.BeginForm("SubmitSelected", "FolderAccess", FormMethod.Post, new { encType = "multipart/form-data"}))
Thiago Ferreira and haim770 Thanks a lot! The solution is to use the combination of your comments. So:
#using (Html.BeginForm("SubmitSelected", "FolderAccess", FormMethod.Post))
at the Controller

KendoUI listview passing IEnumerable<model> instead of model from editor template in MVC

I've been puzzling over this for a few days now. Basically, I have a view model that contains three IEnumerables of other view models to be displayed in three separate Kendo controls - one as a ListView, and two as GridViews. Each view model has a separate editor template that is used by the corresponding control. The GridViews are working 100%, and the Kendo ListView is working properly on the page (the ListView refreshes with the updated data).
My problem is that an IEnumerable of the view model is being passed to the ActionResult (with a null value) instead of just a single instance of the view model, and the DataSourceRequest is empty.
Here is the (redacted) code.
The view models (just the wrapper and view model for the ListView in question):
public class MainPersonViewModel
{
public MainPersonViewModel(){}
public int PersonId { get; set; }
public IEnumerable<DetailsViewModel> PersonDetails { get; set; }
public IEnumerable<AddressViewModel> Addresses { get; set; }
public IEnumerable<PersonGroupingViewModel> MemberOf { get; set; }
}
public class DetailsViewModel
{
public DetailsViewModel(){}
public int PersonId { get; set; }
public string Name { get; set; }
public string WorkingTitle { get; set; }
}
The Kendo ListView template:
#model Staff.ViewModels.MainPersonViewModel
<script type="text/x-kendo-tmpl" id="personDetailsTemplate">
<table>
<tr>
<td>Name: </td><td>${Name}</td>
</tr>
<tr>
<td>Working Title: </td><td>${Title}</td>
</tr>
<tr>
<td colspan="2">
<div class="edit-buttons">
<a class="k=button k-button-icontext k-edit-button" href="\\#"><span class="k-icon k-edit"></span>Edit</a>
</div>
</td>
</tr>
</table>
</script>
And the Kendo control itself:
#(Html.Kendo().ListView<Staff.ViewModels.DetailsViewModel>(Model.PersonDetails)
.Name("personDetailsList")
.TagName("div")
.ClientTemplateId("personDetailsTemplate")
.Editable()
.DataSource(ds => ds
.Model(m =>
{
m.Id(f => f.PersonId);
m.Field(f => f.Name);
m.Field(f => f.WorkingTitle);
}
)
.Read(read => read.Action("ViewPersonDetails", "Staff", new {id = Model.PersonId}))
.Update(update => update.Action("UpdatePersonDetails", "Staff"))
)
)
The ActionResult called by the Listview in the controller is as follows:
public class StaffController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdatePersonDetails([DataSourceRequest] DataSourceRequest request, IEnumerable<DetailsViewModel> toUpdate)
{
//update code here
return Json(ModelState.ToDataSourceResult());
}
}
Finally the editor template (located in Views\Staff\EditorTemplates):
#model Staff.ViewModels.DetailsViewModel
<div>
<table>
<tr>
<td>#Html.LabelFor(m => m.NameFirst)</td>
<td>#Html.EditorFor(m => m.NameFirst)</td>
</tr>
<tr>
<td>#Html.LabelFor(m => m.NameLast)</td>
<td>#Html.EditorFor(m => m.NameLast)</td>
</tr>
<tr>
<td>#Html.LabelFor(m => m.Title)</td>
<td>#Html.EditorFor(m => m.Title)</td>
</tr>
<tr>
<td colspan="2">
<div class="edit-buttons">
<a class="k-button k-button-icontext k-update-button" href="\\#"><span class="k-icon k-update"></span>Save</a>
<a class="k-button k-button-icontext k-cancel-button" href="\\#"><span class="k-icon k-cancel"></span>Cancel</a>
</div>
</td>
</tr>
</table>
</div>
Since the ListView seems to be refreshing I don't think it's necessarily a problem with it or the DataSource on the page, so I'm leaning towards some detail (i.e. limitation) with the editor template that I'm missing. Any thoughts?
Sorry for the long post, and any help would be greatly appreciated!

MVC - Model - View and Controller 's role

Following is my Architecture of an application. I am confuse with whether I understood MVC correct or not? My Architecture is right or not?
View - interacts with the user, it has HTML part, on submit the form it calls controller
Controller - it checks for information added is valid or not? (not database point of view. it will just check for weather all the mandatory fields are filled or not?) decides which model to call.
Model - it contains class of view. and also some methods like add,modify or delete to deal with the database.
Is this correct or making some mistake?
Following is sample of my code
Controller:
public ActionResult AddCustomer(CustomerModel model)
{
if (ModelState.IsValid)
{
model.AddCustomer();
return RedirectToAction("Index", "Home");
}
return (View("AddCustomer",model));
}
Model:
public class AddBookModel
{
[Required(ErrorMessage = "The ISBN is required.")]
[DisplayName("ISBN")]
public String ISBN { get; set; }
[DisplayName("Title")]
[Required(ErrorMessage = "The Title is required.")]
public String Title { get; set; }
[Required(ErrorMessage = "The Publisher is required.")]
[DisplayName("Publisher")]
public String Publisher { get; set; }
public void AddBook()
{
using (BBBDataContext DCBook = new BBBDataContext())
{
Book tableBook = new Book()
{
ISBN = this.ISBN,
Title = this.Title,
Publisher = this.Publisher,
}
DCBook.Books.InsertOnSubmit(tableBook);
DCBook.SubmitChanges();
}
}
View:
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Insert Book Record</legend>
<table id="displayform" cellspacing="0" cellpadding="5">
<colgroup>
<col span="1" style="text-align:right" />
<col span="2" style="text-align:left" />
</colgroup>
<tr>
<td class="editor-label">
<%= Html.LabelFor(model => model.ISBN) %>
</td>
<td class="editor-field">
<%= Html.TextBoxFor(model => model.ISBN) %>
<%= Html.ValidationMessageFor(model => model.ISBN) %>
</td>
</tr>
<tr>
<td class="editor-label">
<%= Html.LabelFor(model => model.Title) %>
</td>
<td class="editor-field">
<%= Html.TextBoxFor(model => model.Title) %>
<%= Html.ValidationMessageFor(model => model.Title) %>
</td>
</tr>
Your understanding of MVC is good.
The view only contains visual elements that will be displayed and doesn't contain any logic code.
The controller is listening to the view's events (mouseClick, lostfocus...), interact with the model, do verifications...
And the model contains your business class and interacts with databases and others external services.

Editor Template in a post call is not passing model correctly

Hi Folks someone help me 2 days ago with a solution to generate several textboxes from a list in the domain model with razor using an editor template, and i put a little js for make it a little more dynamic and all, but when i make the post call to the action method in the controller, it dont refresh the values inside the text fields, i will put some codes here maybe you know what the problem is.
this is want i want to achieve
//AntiBot Field
public string Customer { get; set; }
public int ContentItemId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int UserId { get; set; }
public string Salutation { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
[Display(Name = "Recipients")]
public List<Recipient> Recipients { get
{ return new List<Recipient>
{
new Recipient { Name = "", Email = "" },
//x10
};
}
}
[Required]
[Display(Name = "Nachricht")]
public string Message { get; set; }
}
public class Recipient{
[Display(Name = "Recipient Name:")]
public string Name { get; set;}
[Display(Name = "Recipient Email Address:")]
[DataType(DataType.EmailAddress)]
public string Email { get; set;}
}
each one of this input fields have this properties
so i have up to ten fields and each one of this fields has an id Recipient_(1_10)_Name/Email
this is my view
#using (Html.BeginForm("Submit", "Share"))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.UserId)
#Html.HiddenFor(m => m.ContentItemId)
#Html.TextBoxFor(m => m.Customer, new { #class = "b2a534d1" })
<p>Hi: #Html.DisplayTextFor(m => m.Salutation) #Html.DisplayTextFor(m => m.Firstname) #Html.DisplayTextFor(m => m.Lastname)</p>
<table border="0" style="padding:5">
<tr>
<td class="editor-label">#Html.LabelFor(m => m.Title): </td>
<td class="editor-field">#Html.DisplayTextFor(m => m.Title)
</td>
</tr>
<tr>
<td class="editor-label">#Html.LabelFor(m => m.Description): </td>
<td class="editor-field">#Html.DisplayTextFor(m => m.Description)
</td>
</tr>
<tr>
<td>#Html.LabelFor(m => m.Message)</td>
<td>#Html.TextAreaFor(m => m.Message)</td>
</tr>
</table>
<table >
#Html.EditorFor(m => m.Recipients)
</table>
<table>
<tr>
<td>
Add Recipient</td>
<td><input type="submit" class="button med primary" style="float: right;" value="ABSENDEN" /></td>
</tr>
</table>
}
and this is my recipient
#model PetterLetter.Application.Models.Recipient
<p class="recipient"> Name: #Html.EditorFor(x=>x.Name) Email: #Html.EditorFor(x => x.Email) </p>
and after i debug the solution this is what i get from the model of the view.
this recipient should have the values entered in the input fields of the editor template??
what am i doing wrong?
I had a similar issue with a dynamically loaded form, and the solution can be gleaned from Phil Haack's post.
The upshot is, when you load more than one of these forms, you must assign them a different index value (not [0] every time).
I've solved this by using the hidden field for the collection Index, and assigning it a unique value. It can be anything in reality, like a date time string, as long as the index value is also used in each of the input names. Read the linked post, particularly the non-sequential indices section.

Resources