Problem when trying to render a PartialView in ASP MVC 3 - c#

I have a problem now with ASP MVC 3 when trying to rend a that is stored in a PartialView after an AJAX Request is done. Here is the code of my two views:
#model ICollection<Foo.ViewModels.OrderSearchViewModel>
#using Foo.Helpers
#{
ViewBag.Title = "Sales Order Lookup";
}
#using (Ajax.BeginForm(new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "results",
InsertionMode = InsertionMode.Replace
}))
{
#*"Search","OrderSearch",FormMethod.Get*#
<div id="Criteria" style="width: 800px;margin-left:10%">
<table id="tblSearchCriteria" class="FunnyRedLine" width="100%">
<!-- Many boring search fields here -->
<td style="width: 40%">
<input type="submit" value="Search" class="Text" />
</td>
</tr>
</table>
</div>
}
#Html.Partial("SearchResults",Model)
This is the partial view
#model ICollection<Foo.ViewModels.OrderSearchViewModel>
#using Foo.Helpers
#if (Model.Count > 0)
{
<div id="results" style="width: 800px; margin-left:10%">
<table id="tbl">
<tr>
<th>Sod Id</th>
<th>Sales Ref</th>
<th>SOP Ref</th>
<th>Order Date</th>
<th>Value</th>
<th>Status</th>
<th>Del Date</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td width="30" align="center">#Html.DisplayFor(modelItem => item.Id)</td>
<td width="30" align="center">#Html.DisplayFor(modelItem => item.SalesPersonRef)</td>
<td width="200" align="center">#Html.DisplayFor(modelItem => item.SOPRef)</td>
<td width="100" align="left">#Html.FormatDate(item.OrderDate)</td>
<td width="100" align="right">#Html.FormatNumber(item.Value,"C2")</td>
<td width="300" align="left">#Html.DisplayFor(modelItem => item.Status)</td>
<td width="100" align="left">#Html.FormatDate(item.DelDate)</td>
</tr>
}
</table>
</div>
}
And this is my controller
public class OrderSearchController : Controller
{
//
// GET: /OrderSearch/
[Ajax(false)]
public ActionResult Index()
{
var viewModel = new List<OrderSearchViewModel>();
ViewBag.SalesPeople = GetAllSalesPeople()
ViewBag.OrderTypes = GetAllOrderTypes()
return View(viewModel);
}
[Ajax(true)]
public ActionResult Index(string id, string startDate, string endDate, string postCode, string salesPersonId, string salesPersonRef,
string orderTypeId, string serialNo, string customerPO)
{
var service = new eSodSrv();
var viewModel = service.GetHeaders(id.ToInt32(), salesPersonId.ToInt32(), orderTypeId.ToInt32(), startDate.ToDate(), endDate.ToDate(), postCode, customerPO, serialNo, salesPersonRef);
return PartialView("SearchResults",viewModel);
}
}
The AJAX request is working, it is entering the correct method (Ajax is a custom attribute that checks Request.IsAjaxRequest()) and it is returning data, so why is the view not rendered?

The partial view is not appearing, because your target div is not being rendered. Instead of using #Html.Partial() in your main view, insert the following:
<div id="results" />
This will create the target, where your partial will be inserted.

Related

Passing value to partial view via post

I want to pass a long string from my View to a partial View and render the partial View on Button click.
The string is too long to be passed as a part of the url, so it must be passed via post.
On the click of the Button Details, an ajax function is called, which should pass the required parameter to the partial view and render it.
Unfortunytely this doesn't work, it seems I have an error in my ajax-declaration. When I click the Details Button nothing happens, and the debugger jumps over the ajax declaration.
Here is a part of my View:
<form class="form-inline" asp-controller="Order" asp-action="Details">
<table class="ComplianceTable" id="ComplianceTable">
<thead>
<tr id='tableHeader'>
<th>Res.</th>
<th>Trend</th>
<th>Portfolio</th>
<th>Level</th>
<th>Code</th>
<th>Description</th>
<th>Rule</th>
<th>Test Type</th>
<th>Limit</th>
<th>Result</th>
<th>(Previous)</th>
<th>Severity</th>
<th>Details</th>
</tr>
</thead>
<tbody>
#foreach (var info in Model.ViolationInfo)
{
<tr>
<td>#info.RuleType</td>
<td></td>
<td>#Model.code</td>
<td></td>
<td></td>
<td></td>
<td>#info.RuleName</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
<input type="hidden" id="value1" name="info.Diagnostic">
<button class="btn js-details" type="button" name="Details" data-id="#info.Diagnostic">
Details
</button>
</td>
</tr>
<tr class="info"><td colspan="11">#info.Diagnostic</td></tr>
}
</tbody>
</table>
<div id="getComplianceDetails"></div>
</form>
Here is my PartialView:
#model string
<div id="getComplianceDetails">
<p>Test</p>
<p>
#Model
</p>
</div>
Here is my javascript:
$(document).ready(function () {
$(document).on('click', '.js-details', function (event) {
$("#ComplianceTable tr").removeClass("selected");
$(this).closest('tr').addClass('selected');
var $element = $(event.currentTarget);
var id = $element.data('id');
$.ajax({
url: '#Url.Action("Details", "Order")',
data: {info: id},
type: "POST",
success: function (data) {
$('#getComplianceDetails').html(data);
}
});
});
});
Here is my OrderController:
public ActionResult Details(string info)
{
return PartialView("~/Views/Shared/complianceDetails.cshtml", info);
}
Assuming that your "info" has value, try an explicit url:
url: '/Order/Details',
and maybe you need to add [FromBody] to your action:
public ActionResult Details([FromBody] string info)
{
return PartialView("~/Views/Shared/complianceDetails.cshtml", info);
}

How to pass an array from one view and action to another in ASP.NET MVC?

What I want to achieve:
I want a feature that selects multiple records from the index page on my asp.net mvc website which are redirected to another webpage, where they can be bulk edited.
I am using checkboxes to do this, but I don't know how I can access the contents of this array from another action and view.
For now, this is the code that I have done:
The Index View:
#model IEnumerable<BulkDelete.Models.Employee>
#TempData["employeeIdsToDelete"];
<div style="font-family:Arial">
#using (Html.BeginForm("checking", "Home", FormMethod.Post))
{
<table class="table">
<thead>
<tr>
<td>Checkbox<br /></td>
<th>Name</th>
<th>Gender</th>
<th>Email</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" name="employeeIdsToDelete" id="employeeIdsToDelete" value="#item.ID" /></td>
<td>#item.Name</td>
<td>#item.Gender</td>
<td>#item.Email</td>
</tr>
}
</tbody>
<br />
</table>
<input type="submit" value="Delete selected employees" />
}
</div>
The Controller Actions:
public class HomeController : Controller
{
SampleDBContext db = new SampleDBContext();
public ActionResult Index()
{
return View(db.Employees.ToList()) ;
}
[HttpPost]
public ActionResult UpdateMultipleRecords(IEnumerable<int> employeeIdsToUpdate)
{
return checking(employeeIdsToUpdate);
}
public ActionResult checking(IEnumerable<int>employeeIdsToUpdate)
{
foreach (var e in employeeIdsToUpdate)
{
Employee em = new Employee();
em = db.Employees.Find(e);
em.Name = ViewBag.Signature;
db.Entry(em).State = EntityState.Modified;
db.SaveChanges();
}
return View();
}
Instead of posting to index page. post the form in another page.
#using (Html.BeginForm("{actionNameOfAnotherPage}", "{anotherPageControllerName}", FormMethod.Post))
As you are posting an array of data, Use array indexing for form inputs.
#{ var index = 0;}
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" name="[#index]employeeIdsToDelete" class="mycheckbox" id="employeeIdsToDelete" value="#item.ID" /></td>
<td>#item.Name</td>
<td>#item.Gender</td>
<td>#item.Email</td>
</tr>
#{
index++;
}
}
You can also send them as an Ajax call, and in this scenerio you can also do this without a form.
<div style="font-family:Arial">
<table class="table">
<thead>
<tr>
<td>Checkbox<br /></td>
<th>Name</th>
<th>Gender</th>
<th>Email</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" name="employeeIdsToDelete" class="mycheckbox" id="employeeIdsToDelete" value="#item.ID" /></td>
<td>#item.Name</td>
<td>#item.Gender</td>
<td>#item.Email</td>
</tr>
}
</tbody>
<br />
</table>
<input type="button" onClick="deleteEmployees()" value="Delete selected employees" />
</div>
and below your html page
<script>
function deleteEmployees() {
var checkboxes = document.getElementsByClassName("mycheckbox");
var checkedValues = [];
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
console.log(i);
checkedValues.push(checkboxes[i].value)
}
}
console.log(checkedValues);
$.ajax({
type: "POST",
url: '#Url.Action("YourAction", "YourController")',
data: { employeeIdsToUpdate: checkedValues },
success: function (res) {
if (res.ok) {
window.location = res.returnURL;
}
},
error: function (req, status, error) {
console.log(error);
}
});
}
</script>
and in your POST ACTION you can take these values
[POST]
public ActionResult UpdateEmployees(int[] employeeIdsToUpdate)
{
foreach (int e in employeeIdsToUpdate)
{
Employee em = new Employee();
em = db.Employees.Find(e);
em.Name = ViewBag.Signature;
db.Entry(em).State = EntityState.Modified;
db.SaveChanges();
}
return Json(new { ok = true, returnURL = Url.Action(nameof("YOUR VIEW IN HERE"))});
}
Here are some options for sending array from a View to some controller action:
Post the form to your controller action
Send ajax call to your controller action
MVC Hyperlink pointing to your controller action
Here are some options for sending array from a controller action to some other controller action:
Save data in TempData (its available across controllers)
Save data in browser memory (Temp Storage)
Save data in DB
Save data in Session object
Save data in Cache object
and Please dont forget to mark this as answer ... thanks

Trouble getting textbox value from view to controller in ASP.NET MVC

I'm still a beginner in ASP.NET MVC. I have a project that I am working on right now with two views and 1 controller. 1 scan page, 1 data entry page and 1 controller called LprController.
So on the data entry cshtml I have the button that I'm trying to get the data from called lotnoTBX.
div class="col-md-4 col-sm-offset-3">
<img src="~/Images/Capture.PNG" class="media-object center-block"/>
<div class="block-main col-sm-8 col-sm-offset-4">
<h2>Scan Lot</h2>
<input id="lotnoTBX"/>
<div class="container-fluid row">
<button id="enterBtn" type="submit" class="btn btn-primary btn-group-lg" style="margin-top:5px;" onclick="location.href='#Url.Action("DataEntry", "Lpr")'">Enter</button>
</div>
</div>
</div>
Then on the controller page things are a bit confusing. I'm not sure where to save or how to save the lotnoTBX data. Basically I'm using a webservice to get a query from the result of the textbox and post it to the dataentry page using Models.
public ActionResult ScanPage(FormCollection form)
{
string lotno = form["lotnoTBX"];
Session["lotno"] = lotno;
return View();
}
public ActionResult DataEntry()
{
FCoai.FCWCFT.PCSInterfaceClient client = new FCWCFT.PCSInterfaceClient("BasicHttpBinding_IPCSInterface1");
FCoai.FCWCFT.PCSResult x = client.getCurrentLotDetail(Session["lotno"].ToString());
return View();
}
Then here's the data entry page where I'm trying to post the model's in the cshtml.
<table>
<thead>
<tr>
<th class="table-active">OP</th>
<th class="table-active">Lotno</th>
<th class="table-active">Itemcode</th>
<th class="table-active">Marking</th>
<th class="table-active">Output</th>
</tr>
<tr>
<td #Model.op></td>
<td #Model.lotno></td>
<td #Model.itemCode></td>
<td #Model.marking></td>
<td #Model.output></td>
</tr>
</thead>
</table>
*edit I missed out one actionresult which might have been confusing for some people
Please help.
So I managed to get the textbox values to return. It turns out I had to use a form and a model as a parameter in the controller in order to do so.
Here's the scan lot cshtml
<h2>Scan Lot</h2>
#using (Html.BeginForm("ScanPage"))
{
#Html.TextBoxFor(Model => Model.lotno)
<input type="submit" value="Enter"/>
}
And here are the controllers
public ActionResult ScanPage()
{
return View();
}
[HttpPost]
public ActionResult ScanPage(FCoai.FCWCFT.PCSResult pCS)
{
string lotno = pCS.lotno;
Session["lotno"] = lotno;
return RedirectToAction("DataEntry", "Lpr");
}
public ActionResult DataEntry()
{
FCoai.FCWCFT.PCSInterfaceClient client = new FCWCFT.PCSInterfaceClient("BasicHttpBinding_IPCSInterface1");
FCoai.FCWCFT.PCSResult x = client.getCurrentLotDetail(TempData["lotno"].ToString());
//Passing data from controller to view
ViewData["Lot"] = x;
return View();
}
<div class="row">
<div class="col-md-12">
<table>
<thead>
<tr>
<th class="table-active">OP</th>
<th class="table-active">Lotno</th>
<th class="table-active">Itemcode</th>
<th class="table-active">Marking</th>
<th class="table-active">Routing</th>
</tr>
<tr>
#{
//This is how display data from view to controller
var lot = (FCoai.FCWCFT.PCSResult)ViewData["Lot"];
}
<td>#lot.op</td>
<td>#lot.lotno</td>
<td>#lot.itemCode</td>
<td>#lot.markLow</td>
<td>#lot.rout</td>
</tr>
</thead>
</table>
</div>
</div>
Edit here's my final answer.
Even though I have managed to find the answer to my own question I would appreciate if you guys could give tips on conventions or otherwise that I could have missed out on.

Row to send a List<Object> from Razor page to Update?

I need to send a List back to my controller and update the values on my repository.
But after load the view with the values, update it and click the submit button, I don't know how to get the list with the update values and call the update method from the repository.
I'm using .Net 4.7.2.
HomeController:
[HttpGet]
public ActionResult Nota(string Concurso)
{
List<InscricoesModel> model = new List<InscricoesModel>();
InscricoesRepository repository = new InscricoesRepository();
model = repository.GetAprovadosPrimeiraFase(new Guid(Concurso));
return View("Nota",model);
}
[HttpPost]
public void UdateNotas(List<InscricoesModel> model)
{
InscricoesRepository repository = new InscricoesRepository();
foreach(InscricoesModel item in model)
{
repository.Update(item);
}
}
Nota.cshtml:
#model List<ConcursoBolsaSegundaFase.Model.InscricoesModel>
<h1>Classificados 2ª Fase</h1>
<hr />
<p>Exportado em #DateTime.Now</p>
<div style="margin-top:15px">
#* TABELA RESULTADO *#
<div id="notasAprovadosSegundaFase" style="margin-top:10px">
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-bordered" id="tblNotaAprovadosSegundaFase">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var linha in Model)
{
<tr>
<td>#linha.Inscricao</td>
<td>#linha.Nome</td>
<td>#linha.NotaPrimeiraFase</td>
<td>
<select>
<option value="false">Não</option>
<option value="true">Sim</option>
</select>
</td>
<td><input type="text" value="#linha.NotaSegundaFase"></td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
</div>
</div>
The UpdateNotas method in my controller never recive a value, i don't know how to send the list from the view to my controller.
In MVC, the name of the input will be binded to the variable in the controller. In your case, your input has no name. I suggest you look at the html helpers.
This would bind your values properly.
for (int i = 0;i<Model.Count;i++)
{
Html.TextBoxFor(model => Model[i].NotaSegundaFase)
}
In this case, only NotaSegundaFase would be sent back to the controller.
You can use #Html.HiddenFor() to hold the data on the view and bind to controller on Post.
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-striped table-bordered table-sm table-responsive">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(model => Model[i].Inscrição)
#Html.HiddenFor(model => Model[i].Nome)
#Html.HiddenFor(model => Model[i].NotaPrimeiraFase)
<tr>
<td>#Model[i].Inscrição</td>
<td>#Model[i].Nome</td>
<td>#Model[i].NotaPrimeiraFase</td>
#*do this similary for other property *#
</tr>
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
As far as I understood,you want to post DropDownList value only.
if you decide to update other fields just add the Html.Editor into the loop like following.
#Html.Editor("[" + i + "].Inscricao")
#Html.Editor("[" + i + "].Nome")
I hope this will help.
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-bordered" id="tblNotaAprovadosSegundaFase">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Model[i].Inscrição</td>
<td>#Model[i].Nome</td>
<td>#Model[i].NotaPrimeiraFase</td>
<td>
<select name="[#i].NotaSegundaFase">
<option value="false">Não</option>
<option value="true">Sim</option>
</select>
</td>
<td><input type="text" value="#linha.NotaSegundaFase"></td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
Note : don't change anything in the controller. model binder should resolve everything from the request.

Passing model with list of checkboxes from view to controller

I am trying to pass model from View back to controller. I am passing NaborViewModel to View. It is a list of objects and every object has 4 checkboxes (some of them randomly checked).
Model:
public class NaborViewModel
{
public List<WowClass> WowClasses { get; set; }
}
Actions:
[HttpGet]
public ActionResult Nabor()
{
NaborViewModel viewModel = new NaborViewModel();
DatabaseDataContext context = new DatabaseDataContext();
viewModel.WowClasses = context.WowClasses.ToList();
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Nabor(NaborViewModel model)
{
//DB actions
return RedirectToAction(Consts.ActionNabor);
}
In view i have 2 forms each with different approach. The first one is the one i have created with thought it might work.
The second form is approach i found online.
The first one is displaying passed data correctly (filled checkboxes). The second one is even displaying every checboxes unchecked.
When forms are submitted, they both returns null back to controller action.
View:
#using (Html.BeginForm(Consts.ActionNabor, Consts.ControllerAdmin, FormMethod.Post))
{
#Html.AntiForgeryToken()
<table class="admin-table">
<thead>
<tr>
<th>Class</th>
<th>Status</th>
<th colspan="3">Požadované talenty</th>
</tr>
</thead>
<tbody>
#foreach (var cls in Model.WowClasses)
{
<tr>
#Html.HiddenFor(x => cls.Id)
<td>#cls.ClassName</td>
<td>#Html.CheckBoxFor(x => cls.Open)</td>
<td style="text-align: left">#Html.CheckBoxFor(x => cls.NeedTalents1) <span>#cls.Talents1</span></td>
<td style="text-align: left">#Html.CheckBoxFor(x => cls.NeedTalents2) <span>#cls.Talents2</span></td>
<td style="text-align: left">#Html.CheckBoxFor(x => cls.NeedTalents3) <span>#cls.Talents3</span></td>
</tr>
}
</tbody>
</table>
<input type="submit" value="#Consts.Submit" />
}
<div class="horizontal-line-both"></div>
#using (Html.BeginForm(Consts.ActionNabor, Consts.ControllerAdmin, FormMethod.Post))
{
#Html.AntiForgeryToken()
<table class="admin-table">
<thead>
<tr>
<th>Class</th>
<th>Status</th>
<th colspan="3">Požadované talenty</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.WowClasses.Count; i++)
{
<tr>
<td>
<input type="text" value="#Model.WowClasses[i].ClassName" name="Expense[#i].Id">
</td>
<td>
<input type="checkbox" value="#Model.WowClasses[i].Open" name="Expense[#i].Id">
</td>
<td>
<input type="checkbox" value="#Model.WowClasses[i].NeedTalents1" name="Expense[#i].Id">
</td>
<td>
<input type="checkbox" value="#Model.WowClasses[i].NeedTalents2" name="Expense[#i].Id">
</td>
<td>
<input type="checkbox" value="#Model.WowClasses[i].NeedTalents3" name="Expense[#i].Id">
</td>
<td>
<input type="hidden" value="#i" name="Expense[#i].Id">
</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="#Consts.Submit" />
}
I got this to work with a combination of your two approaches. See the following:
#for (int i = 0; i < Model.WowClasses.Count; i++)
{
...
<tr>
#Html.EditorFor(model => model.WowClasses[i].Open)
</tr>
...
}
Accessing each item in your List via its index is key. If you look at the HTML generated using this method, each item's name includes its index (in the example above, the generated input's name is this: name="WowClasses[0].Open"). This is how your controller action can distinguish between list items.
For your second form, you can modifying every input field like this,
for check box,
<input type="checkbox" id="WowClasses_#(i)_Open" name="WowClasses[#i].Open" value="true" />
for input filed,
<input type="checkbox" id="WowClasses_#(i)_ClassName" name="WowClasses[#i].ClassName" value="true" />
you just changes your every input filed by your class property.hopefully this your help

Categories