Delete and Update List of Objects in Asp.Net MVC 4 - asp.net-mvc

I have a form that has an input section at the top of the page and in the bottom half it displays a list of the objects that were added. I need to be able to Edit and Delete these objects and I'm not sure where to start or how to do it.
This code display the list of objects.
#if (Model.ListOfRecipients != null)
{
for (int i = 0; i < Model.ListOfRecipients.Count; i++)
{
<div class='recipient-wrapper'>
<div class='decision_block'>
<table class='recipient'>
<tr>
<td class='recipient-title'>
#Html.HiddenFor(model=>model.ListOfRecipients[i].RecipientId)
<h3>
#Html.DisplayTextFor(model => model.ListOfRecipients[i].RecipientName)
#Html.HiddenFor(model => model.ListOfRecipients[i].RecipientName)
</h3>
<div class='delivery-type'>
Delivery Type: #Html.DisplayTextFor(model => model.ListOfRecipients[i].DeliveryType)
#Html.HiddenFor(model => model.ListOfRecipients[i].DeliveryType)
</div>
</td>
<td class='na express'>
#Html.CheckBoxFor(model => model.ListOfRecipients[i].ExpressIndicator)
#Html.HiddenFor(model => model.ListOfRecipients[i].ExpressIndicator)
</td>
<td class='quantity'>
<h3>
Qty #Html.DisplayTextFor(model => model.ListOfRecipients[i].Quantity)
#Html.HiddenFor(model => model.ListOfRecipients[i].Quantity)
</h3>
</td>
<td class='action'>
<input class='button edit_recipient' type='button' value='Edit' />
<input class='button delete_recipient' type='button' value='Delete' />
</td>
</tr>
</table>
<input class='button update_recipient' type='button' value='Update' />
<a class='cancel_update' href='#'>Cancel</a>
</div>
</div>
</div>
}
}

You need to write Edit and Delete action methods in your controller and then set your two buttons to call the appropriate method.
The code for the action methods will depend on several factors that may to broad to address here.
Using Razor Syntax -- sorry the others were using wrong markup:(
<input class='button edit_recipient' type='button' value='Edit'
onclick="location.href='#Url.Action("Edit", "Controller", new { id = Model.Id } )'" />

You could create a delete controller and an edit controller and in the above view have a beside each one that has a delete and edit which recieves the objects id and each button goes to it's own view where they can edit or delete

Related

ASP MVC 5 Post a form from a link

I need to make a custom data grid view with multi column filtering and pagination. so i made a view model winch will encapsulate three class
IEnumerable from the data.
Filter class with some properties
Pager to holder page size, current page, total pages etc ..
Filtering working fine but pagination not :(. as i loose the view model when pressing pagination link "It seems that i need to also submit the search form"
Any one can show how i can submit the form when pressing a link.
here is my view
#model TestFilteringAndPagination.ViewModels.CarViewModel
#{
ViewBag.Title = "Home Page";
}
#*Search form*#
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "frm" }))
{
#Html.HiddenFor(m => Model.Pager.CurrentPage)
#Html.HiddenFor(m => Model.Pager.PageSize)
#Html.HiddenFor(m => Model.Pager.EndPage)
#Html.HiddenFor(m => m.Pager.StartPage)
<div class="form-inline">
<div class="form-group">
<label>Car No</label>
#Html.EditorFor(x => x.Filter.CarNumber, new { #class = "form-control" })
</div>
<div class="form-group">
<label>Line name</label>
#Html.EditorFor(x => x.Filter.LineName, new { #class = "form-control" })
</div>
<button type="submit" class="btn btn-default">Search</button>
</div>
<ul class="pagination">
#for (var page = Model.Pager.StartPage; page <= Model.Pager.EndPage; page++)
{
<li class="#(page == Model.Pager.CurrentPage ? "active" : "")">
#page
</li>
}
</ul>
}
#*Data grid*#
<table class="table">
<thead>
<tr>
<th>
Car number
</th>
<th>
Car Line
</th>
</tr>
</thead>
<tbody>
#foreach (var car in Model.Cars)
{
<tr>
<td>
#Html.DisplayFor(x => car.CarNumber)
</td>
<td>
#Html.DisplayFor(x => car.LineName)
</td>
</tr>
}
</tbody>
</table>
You can install the PagedList.MVC NuGet Package, see this post for more info about how to create exactly what you want.
Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application

Model is null with Html.BeginForm() ASP.NET MVC

I encountered following problem:
user visits site, clicks "Add" and then it's sending back to Controller, Model is retrieved and send to View one more time. Inside view, I check whether Model is not null
and displays data.
#if (Model != null)
{
<div id="appInfo">
<table>
<tr>
<th>#Html.DisplayNameFor(x => Model.tytul)</th>
<th>#Html.DisplayNameFor(x => Model.kategoria.nazwa)</th>
<th>#Html.DisplayNameFor(x => Model.liczba_ocen)</th>
<th>#Html.DisplayNameFor(x => Model.avg_ocena)</th>
<th>#Html.DisplayNameFor(x => Model.typ)</th>
</tr>
<tr>
<td>#Model.tytul</td>
<td>#ViewData["kategoria"]</td>
<td>#Model.liczba_ocen</td>
<td>#Model.avg_ocena</td>
<td>#Model.typ</td>
</tr>
</table>
</div>
<div>
#using (Html.BeginForm("Confirm", "Wydawca", new { app = #Model }))
{
<input type="submit" value="Cofirm it" />
}
</div>
At the end button "Confirm it" is created and once you click it invokes Confirm Method but app variable is always null. If I set its value to anything but Model it works.
[HttpPost]
public ActionResult Confirm(aplikacja app)
{
...
}
While creating button "Confirm it" Model is not null, I checked. Do you happen to know what is going wrong?
Generated html
<form action="/Wydawca/Confirm?app=Adds.Models.aplikacja" method="post">
<input type="submit" value="Zatwierdź" />
The Html.BeginForm should wrap around all of your input elements or it has nothing to post. Change your view to this:
#if (Model != null)
{
#using (Html.BeginForm("Confirm", "Wydawca", new { app = #Model }))
{
<div id="appInfo">
<table>
<tr>
<th>#Html.DisplayNameFor(x => Model.tytul)</th>
<th>#Html.DisplayNameFor(x => Model.kategoria.nazwa)</th>
<th>#Html.DisplayNameFor(x => Model.liczba_ocen)</th>
<th>#Html.DisplayNameFor(x => Model.avg_ocena)</th>
<th>#Html.DisplayNameFor(x => Model.typ)</th>
</tr>
<tr>
<td> #Model.tytul</td>
<td>#ViewData["kategoria"]</td>
<td>#Model.liczba_ocen</td>
<td>#Model.avg_ocena</td>
<td>#Model.typ</td>
</tr>
</table>
</div>
<div>
#Html.HiddenFor(x => Model.tytul)
#Html.HiddenFor(x => Model.kategoria.nazwa)
#Html.HiddenFor(x => Model.liczba_ocen)
#Html.HiddenFor(x => Model.avg_ocena)
#Html.HiddenFor(x => Model.typ)
<input type="submit" value="Cofirm it" />
</div>
}
}
You are attempting to pass an object (#Model) as a route parameter (app). Route parameters should contain scalar values (int, string, etc), not objects. View the generated HTML source in the browser and see what the <form action=""> is being set as. Then review the concept of model binding.

Disable unobtrusive validation on an ASP.NET MVC form

I have two forms on a page. I want the first form to use unobtrusive validation, as it's since automatically generated by ASP.NET MVC Framework. There is a second form, however, which I wrote manually, that should not use unobtrusive validation.
Here's some code:
#using (Html.BeginForm("Add", "Contacts", FormMethod.Post, new { id = "AddForm" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Datos Contacto</legend>
<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>
<div class="editor-label">
#Html.LabelFor(model => model.ContactDepartmentID)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ContactDepartmentID, (List<SelectListItem>)ViewBag.ContactDepartments)
#Html.ValidationMessageFor(model => model.ContactDepartmentID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Sex)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Sex, (List<SelectListItem>)ViewBag.Sexs)
#Html.ValidationMessageFor(model => model.Sex)
</div>
</fieldset>
<br />
#Html.HiddenFor(model => model.SerializedEmails, new { data_bind = "value: ko.toJSON($root.emails())" })
#Html.HiddenFor(model => model.SerializedPhones, new { data_bind = "value: ko.toJSON($root.phones())" })
}
<form id="phoneForm" >
<fieldset>
<legend>Teléfonos</legend>
<table class="table">
<tbody data-bind="foreach: phones">
<tr>
<th>
Celular?
</th>
<th>
Phone
</th>
<th>
Extension
</th>
<th>
</th>
</tr>
<tr>
<td>
<input type="checkbox" data-bind="checked: isMobile" />
</td>
<td>
<input class="phone" data-bind='value: phone'/>
</td>
<td>
<input type="text" class="extension" data-bind='value: phoneExtension, enable: !isMobile() ' />
</td>
<td>
<a href='#' data-bind='click: $root.removePhone'>Delete</a>
</td>
</tr>
</tbody>
</table>
<a href='#' data-bind='click: $root.addPhone'>Agregar teléfono</a>
</fieldset>
</form>
<p>
<button onclick="Submit();" type="button" class="btn btn-primary" data-bind='enable: phones().length > 0 || emails().length > 0'>
Create</button>
</p>
JS:
function Submit()
{
var valid = $('#AddForm').valid();
var valid2 = $('#phoneForm').valid();
}
jQuery.validator.addClassRules("phone", {
required: true
});
As a side note: When I remove the unobtrusive validation from the page, the second form validates, but the first does not. If I use unobtrusive validation the first form validates, but the second form does not.
I know I can do the whole validation on the client side—and, if that's the only way, I will do it. I was thinking about a way to continue using unobtrusive validation, but allowing it to be conditionally disabled using e.g. custom attributes.
You can disable the unobtrusive validation from within the razor code via this Html Helper property:
HtmlHelper.ClientValidationEnabled = false;
That way you can have unobtrusive validation on and off for different forms according to this setting in their particular view/partial view.
You can mark the elements or find it all the input of the second form and remove the rules, this sample is for remove all rules of some controls in the form, this cause according with the user selected some options, the values required will be others. for this reason i store the rules to restore it later.
///Remove rules
$("input.rO,textarea.rO").each(function () {
try
{
var rule = $(this).rules();
if (rule) {
$(this).data("rule", rule);
$(this).rules("remove");
}
}
catch(err){}
});
///Restore rules
$("input.rO.om" + v + ",textarea.rO.om"+v).each(function () {
try
{
var rule = $(this).data("rule");
if (rule)
$(this).rules("add", rule);
}
catch(err){}
});

Trying to figure out Ajax.BeginForm

I have a view in 2 sections.
The top section I input fields and submit to save them.
In the second section I have an autocomplete textbox. I select an item in autocomplete, and when I click submit I want to add that item to a datatable.
So for the first part when I click submit I save the details via a HttpPost method on the controller.
For the second part I intend to save it via an Ajax call for the controller and then bring back a partial view with the results. I have not coded the partial view yet, that is next.
Now I am new to Ajax.BeginForm and I am struggling with it.
I was hoping that the submit button inside the Ajax.BeginForm would only apply to that part of the form.
But in fact it calls the HttpPost method for the whole form.
So how do I fix this?
My view looks like;
#using ITOF.HtmlHelpers
#model ITOF.Models.OngoingContractViewModel
#{
ViewBag.Title = "EditOngoingContractDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("EditOngoingContractDetails", "Contract", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Contract.ContractId)
<h1>Edit Ongoing Contract Details</h1>
<fieldset>
<legend>#Model.Contract.Heading</legend>
<p>Where you see <span class="error">*</span> you must enter data.</p>
<table>
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.EndDate)
</td>
<td>
#Html.EditorFor(model => model.Contract.EndDate)
</td>
</tr>
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.Organogramme)
</td>
<td>
<input type="file" id="PDF" name="file" />
#Html.HiddenFor(model => model.Contract.Organogramme)
</td>
</tr>
#if (!string.IsNullOrWhiteSpace(Model.Contract.Organogramme))
{
<tr>
<td></td>
<td>
The current organogramme is <span class="HighlightTextRed">#Model.GetOrganogrammeName()</span>
for the contract <span class="HighlightTextRed">#Model.Contract.ContractName</span><br/>
Click here to see the last saved organogramme
</td>
</tr>
}
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.AssistantRLOManagerId)
</td>
<td>
#Html.DropDownListFor(model => model.Contract.AssistantRLOManagerId, Model.AssistantRloManagerSelectList, "--N/A--")
</td>
</tr>
#if (this.TempData["SuccessMessage"] != null)
{
<tr>
<td colspan="2" class="success">#this.TempData["SuccessMessage"].ToString()</td>
</tr>
}
<tr>
<td colspan="2" style="padding-top: 20px; text-align: center;"><input type="submit" value="Save" /></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>Add an existing Site to this contract: </legend>
#using (Ajax.BeginForm("AddExistingSite", new AjaxOptions { UpdateTargetId = "siteRows" }))
{
<input type="text" name="q" style="width: 800px"
data-autocomplete="#Url.Action("SiteSearch", "DataService", new { contractId = #Model.Contract.ContractId })" />
<input type="submit" value="Add site to contract" />
}
#if (Model.SiteList.Count > 0)
{
<table id="siteDataTable" class="display">
<thead>
<tr>
<th>Main Site?</th>
<th>Type</th>
<th>Address</th>
<th>Map</th>
<th>Telephone</th>
<th>Email</th>
</tr>
</thead>
<tbody id="siteRows">
#foreach (var item in Model.SiteList)
{
<tr id="#item.SiteContract.SiteContractId">
<td>#item.SiteContract.MainSiteFlag</td>
<td>#item.Site.SiteType</td>
<td>#item.Site.Address</td>
<td>#item.Site.MapUrl</td>
<td>#item.Site.Telephone</td>
<td>#item.Site.Email</td>
</tr>
}
</tbody>
</table>
<div class="add_delete_toolbar" />
}
#Html.ListLink("Back to List")
</fieldset>
}
Oh no, you just cannot nest HTML forms. That's not supported. You will have to rethink your design. This really has absolutely nothing to do with ASP.NET MVC and things like Html.BeginForm or Ajax.BeginForm. The HTML specification simply tells you that the <form> tag cannot be nested and if you nest it you will get undefined behavior that could vary between browsers.
For example you could implement the autocomplete functionality using jquery UI autocomplete plugin and get rid of the Ajax.BeginForm.

Can one handle Multiple Post Form Actions on One View in MVC

Just need to if i can use to form=post in the mvc view , below is the example which uses to form post , which currently doesnt works:
Edited: the jquery is submiting the form with id frmWorldPay when the image is clicked
$("#pay").click(function () {
// $("#frmWorldPay").(function () {
if ($("#terms").attr("checked")) {
$("#frmWorldPay").submit();
alert("sss");
// return true;
} else {
alert("Please agree to the terms and conditions.");
return false;
}
});
<% using (Html.BeginForm()) {%>
<table id="cart" border="0" cellpadding="0" cellspacing="0">
<tr>
<th>
Event
</th>
<th>
Item
</th>
<th>
Quantity
</th>
</tr>
<%
foreach (var bookingItem in Model.BookingItems)
{%>
<tr>
<td>
<%: ViewBag.Name %>
</td>
<td>
<%: Product.Description %>
</td>
<td>
<%: bookingItem.Quantity%>
</td>
</tr></table>
<% } %>
<% { %> if (ViewBag.mode == "confirm")
{ %>
<input type="submit" value="Confirm" />
<% } %>
<form method="post" action="https://secure.wp3.rbsworldpay.com/wcc/purchase" id="frmWorldPay">
<input type="hidden" name="instId" value="01" />
<input type="hidden" name="cartId" value="<%: Model.GUID %>" />
<input type="hidden" name="currency" value="GBP" />
<input type="hidden" name="testMode" value="100" />
</form> if (ViewBag.mode == "Checkout")
{ %>
<div id="worldPayBtnWrap">
<p> <%: Html.CheckBox("terms") %> by ticking this box you are agreeing to our <%: Html.ActionLink("terms & conditions", "Terms", "About")%></p>
<input type="image" src="/content/images/btnWorldPay.png" alt="Pay via World Pay" id="pay" />
</div>
<% } %>
You can have multiple forms in one web page, but you can't nest them.
Your external form is nested inside the MVC form (the using (Html.BeginForm()) { }), so it won't work.
I have sorted out the issue , actually my input was in same post method , therfore only one form was posting while the other input was not posting , the above is modified which works fine , although it is not a clean solution , for the time being i will be happy to use , will clean it later on .:)

Resources