ASP .NET MVC Ajax insert view instead instead replace data only first time - ajax

I'm new to AJAX, and I have a very simple example, but has a problem; first call the data is duplicated at the View and in subsequent calls work correctly. What am I doing wrong?
The ~/Views/Shared/_Layout.cshtml file had all scripts necesary:
<script src="~/Scripts/jquery-3.1.0.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
First time, the initial view:
Second time, first time button click inserts a number instead of replace number:
Third time, second time button click works fine but in the second line number... an so on:
This is my code:
Model
namespace MQWebSt.Models
{
public class AjaxTest
{
public int Number { get; set; }
}
}
Controller:
using System.Web;
using System.Web.Mvc;
using MQWebSt.Models;
namespace MQWebSt.Controllers
{
public class AjaxTestController : Controller
{
// GET: AjaxTest
public ActionResult Vista()
{
AjaxTest at = new AjaxTest { Number = 1 };
return View(at);
}
[HttpPost]
public ActionResult Vista( AjaxTest model)
{
Random rnd = new Random();
model.Number = rnd.Next(1, 100);
return PartialView("AjaxTestPartial", model);
}
}
}
View Vista.chtml:
#model MQWebSt.Models.AjaxTest
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Ajax.BeginForm("Vista", new AjaxOptions { UpdateTargetId = "divEmp", InsertionMode = InsertionMode.Replace }))
{
<button class="btn btn-primary btn-md glyphicon glyphicon-menu-right" name="Contestar" type="submit" value="+1"></button>
<div class="panel panel-footer">
<table id="divEmp">
#Model.Number.ToString()
</table>
</div>
}
AjaxTestPartial.chtml:
#model MQWebSt.Models.AjaxTest
#Model.Number.ToString()

The issue is you're using InsertionMode = InsertionMode.Replace, it's going to replace the data in the UpdateTargetId. You could use InsertionMode.InsertBefore instead and it would build the values out in the parent of #divEmp. However, if you need the values to be placed in #divEmp, you'll need to write a JavaScript handler for the OnSuccess option of your Ajax form, that way you can dictate if you're doing insert vs. pre-pend vs. replace.

The issue is, your HTML markup code in your razor view is not valid. With the code you have, razor will generate the below markup (Check the view source)
<div class="panel panel-footer">
1
<table id="divEmp"></table>
</div>
You can see that 1 is not inside the table. It is outside. So when your ajax form submit happens, it will update the tables content with the new value. that is the reason you are still seeing the initial number.
The solution is to change the table to a div/span
<div id="divEmp"> #Model.Number.ToString() </div>
Or if you absolutely need to have a table for any reason, have the value inside a td and use "divEmp" as the id attribute value of that.
<table >
<tr>
<td id="divEmp">1</td>
</tr>
</table>

Related

nested partial View calling HttpPost method 2 times

I have seen this question being asked few times here , but solution I saw are not generic , they are related to their specific code ..
I need to rectify the Work done by previous developer , the flow of ajax calls are wrong in code
In my Situation I have views like :
1.Index (Main View)
2.ParentCategoryList (partial View inside Index)
3. AddChild (partial View inside ParentCategoryList )
4. childCategorytree (Seperate View )
Problem is that from 2nd nested View (AddChild ) , whhen i click on save button ,httpost method is calling twice
My Index View
<div>
<div class="content" id="divparent">
</div>
<div class="content" id="dvChild">
</div>
</div>
its script
#section scripts{
<script type="text/javascript">
$('document').ready(function () {
//------------
$.get('#Url.Action("ParentCategoryList", "List")', function (data) {
$("#divparent").html("");
$("#divparent").html(data);
});
})
function addnewchild(url) {
$.get(url, function (data) {
$("#dvChild").html("");
$("#dvChild").html(data);
});
}
</script>
}
First Partial View inside Index (ParentCategoryList.cshtml)
#foreach (Bmsa.UI.Models.ListsResultModel data in Model)
{
<tr> <td><a onclick="addnewchild('#Url.Action("AddChild",
"List", new { id = #data.listID })')" >
</a> </td></tr> } </tbody> </table>
2nd Nested Partial View inside ParentCategoryList
#using (Ajax.BeginForm("AddChild", "List", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "dvChild"
}))
{
<div > <input type="submit" value="Save" /></p></div>}
and Controller methods
public ActionResult ParentCategoryList()
{
//Code
return PartialView("ParentCategoryList", categoryList); }
//GET Operation to Load this View
public ActionResult AddChild(int id)
{
ViewBag.ParentID = id;
ListsAddModel addchild = new ListsAddModel();
addchild.parentListId = id;
return PartialView("AddChild", addchild);
}
[HttpPost] (**this method is calling twice--this is the problem** )
public ActionResult AddChild(ListsAddModel model,int id)
{
//Code
return RedirectToAction ("ChildCategoryListTree", new { id = model.parentListId });
}
and childCategorytree Partial view (also blank one)
I am not able to prevent this method to called twice . I tried e.preventDefault() in $.ajax call , but it is not working ...
I have tried to minimise the code , I think the problem is in RedirectToAction , but I am not sure
Any Help would be appreciated

partial views to get data and then post the results to save in database

I am very new to MVC, let me try to explain my scenario in plain simple English:
I have an strongly typed mvc form/page (Product.cshtml) with a model, say ProductViewModel.
This page has got two search buttons, one to search and bring the items to be added to the Product and other to bring in the location, most probably partial views.
Now, what I want is that these search results work in ajax form without complete post back, and then the results of these searches (items and location) should be posted back using model binding to the form when user clicks on the submit button.
What could be the best way of achieving this functionality?
Immediate responses will be well appreciated.
I thought, its good to share the complete code for clarity:
I have one form(Service1.chtml) that has a partial view to display users(_TestUser a partial view:read only), then another partial view(_PlotServiceRequestData) that should have a field to search the plot and bring back the details lke its owner name and landuser etc.
Then when I click on submit button of the main form, I should be able to read all data(main form) + new data from _PlotServiceRequestData partial view and save all data to database.
I was trying one more option, that is, to use #Ajax.ActionLink on Service1.cshtml to call the _GetPlotDetails method and then store partial view data in TempData, so that it is available to the form when users clicks on "Submit" button of Service1.cshtml, is this a right approach?, if I use ajax.BeginForm inside partial view then the data is posted to the
Service1 controller method which is actually to save the form data and not to update the partialview and in this method even I am not getting model data of the partial view.
Sevice1.cshtml:
#model ViewModels.TestViewModel
#{
ViewBag.Title =
"Service1";
}
#
using (Html.BeginForm())
{
#Html.LabelFor(m => m.Title)
#Html.EditorFor(m => m.Title)
#Html.Partial(
"_TestUser", Model)
<div id="RequestPlotData">
#Html.Partial(
"_PlotServiceRequestData", Model.requestData)
</div>
<button type="submit">Save Form</button>
}
#section Scripts {
}
_PlotServiceRequestData.cshtml:
===============================
#model ViewModels.PlotServicesRequestDataViewModel
<
div id="RequestPlotData">
#
using (Ajax.BeginForm("_GetPlotDetails", "Test", new AjaxOptions { UpdateTargetId = "RequestPlotData", Url = Url.Action("_GetPlotDetails","Test") }))
{
<h1>Request Details</h1>
 
<div>
#Html.LabelFor(m => m.plotAddress)
#Html.EditorFor(m => m.plotAddress)
<input type="submit" name="submit" value="Ajax Post" />
</div>
<div>
#Html.LabelFor(m => m.LandUser)
#Html.EditorFor(m => m.LandUser)
</div>
<div>
#Html.LabelFor(m => m.OwnerName)
#Html.EditorFor(m => m.OwnerName)
</div>
}
</
div>
CONTROLLER:
==========
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
namespace
TestNameSpace
{
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Service1()
{
Injazat.AM.mServices.
LocalDBEntities context = new Injazat.AM.mServices.LocalDBEntities();
TestViewModel model =
new TestViewModel() { user = context.Users.First(), Title = "Land Setting Out",
requestData =
new PlotServicesRequestDataViewModel() { ServiceNumber ="122345", TransactionDate="10/10/2033" } };
return View(model);
}
[
HttpPost()]
public ActionResult Service1(TestViewModel model)
{
PlotServicesRequestDataViewModel s = (PlotServicesRequestDataViewModel)TempData[
"Data"];
TestViewModel vm =
new TestViewModel() { user = model.user, requestData = s, Title = model.Title };
return View(vm);
 
}
[
HttpGet()]
//public PartialViewResult _GetPlotDetails(string add)
public PartialViewResult _GetPlotDetails(PlotServicesRequestDataViewModel requestData)
{
//PlotServicesRequestDataViewModel requestData = new PlotServicesRequestDataViewModel() { plotAddress = add};
requestData.OwnerName =
"owner";
requestData.LandUser =
"landuser";
TempData[
"Data"] = requestData;
return PartialView("_PlotServiceRequestData", requestData);
}
}
}
You can probably use the jQuery Form plugin for this. This makes the process of posting the data from your form back to the server very easy. The form would post to an action that would return a partial view that you can then push into your UI.
To make this easier, jQuery form actually has a "target" option where it will automatically update with the server response (ie. the partial view returned from your search action).
View
<form id="searchForm" action="#(Url.Action("Search"))" method="POST">
<input name="query" type="text" /> <!-- order use Html.TextBoxFor() here -->
<input type="submit" />
</form>
<div id="result"><!--result here--></div>
Javascript
$('#searchForm').ajaxForm({
target: '#result'
});
Controller
public ActionResult Search(string query)
{
// Do something with query
var model = GetSearchResults(query);
return Partial("SearchResults", model)
}
This should hopefully help you to get on the right track. jQuery Form is a good plugin and is the main thing you should look into for ajaxifying your form posts back to the server. You might also want to look into using jQuery's $.post and $.ajax functions, but these require slightly more work.

Update partial view after edit

I have the following index:
<div id='addProduct'>
#{ Html.RenderPartial("Create", new BoringStore.Models.Product()); }
</div>
<div id='productList'>
#{ Html.RenderPartial("ProductListControl", Model.Products); }
</div>
The partial Create view contains an invisible div which is used to create a new product.
After doing so the partial view ProductListControl is updated.
Now I want to do so with an edit function.
Problem: It's not possible to integrate the edit page while loading the index because at this moment I don't know which product the user wants to edit.
My thought:
I'd like to call my existing edit view in an jquery modal (not the problem) so the user can perform changes.
After saving the modal is closed (still not the problem- I could handle this) and the ProductListControl is updated (here's my problem ... :().
How am I able to do so?
I've seen some tutorials but I'd like to keep it as clean & easy as possible.
Most of them are using dom manipulating and get feedback from the server (controller) by a JsonResult.
If possible I'd like to stick to the razor syntax, no pure JavaScript or jquery and if possible I'd like to avoid JsonResults.
One way might be to use the Ajax.BeginForm for your create product view.
The Ajax.BeginForm accepts a number of AjaxOptions, one being the UpdateTargetId (your DOM id, in this case your productlist div), more info here.
Then in your product controller code you can return a partial view, with the product list. So for example:
Index.cshtml
#using (Ajax.BeginForm("AjaxSave", "Product", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "productList", InsertionMode = InsertionMode.Replace }))
{
// your form
<p>
<input type="submit" value="Save" />
</p>
}
...
<div id="productList">...
</div>
ProductController.cs
[HttpGet]
public ActionResult AjaxSave(Product product)
{
if (ModelState.IsValid)
{
// save products etc..
}
var allProducts = _productService.GetAllProducts();
return PartialView("ProductListControl", allProducts);
}
There is a nice article on about this here.

asp.net MVC 3 - JQuery ajax $.get return <nonscript> reCaptcha instead of actual html in partial view

This problem is kind of difficult to explain, but I'll do my best.
I'm simply trying to render the reCaptcha input on a form that is embedded inside a partial view.
Here's how I'm obtaining the partial view with JQuery $.get:
GetAndRenderPartialContent: function (url, obj) {
$.get(url, function (data) {
obj.replaceWith(function () {
var content = "<div id=\"" + obj.attr('id') + "\">" + data + "</div>";
return content;
});
});
}
This works great as a JQuery extension method.
The URL that's passed in to this method is simply a controller route that returns a partial view like this:
public ActionResult GetSomeContent()
{
var model = new SomeModel();
// set modal values
// Finally return partial view
return PartialView("_MyPartialView", model);
}
This works great. It even renders form values bound to the model.
The problem is only with reCaptcha. In my view I have this line to render the reCaptcha:
#Microsoft.Web.Helpers.ReCaptcha.GetHtml(theme: "clean", publicKey: ConfigurationManager.AppSettings["reCaptcha:publicKey"], language: "en")
This works when I embed it directly in the parent view.However, when it is rendered from the partial view method, I get the following results:
<noscript>
<iframe frameborder="0" height="300px" src="http://www.google.com/recaptcha/api/noscript?k=[MY PUBLIC KEY REMOVED FOR DEMO]" width="500px"></iframe>
<br /><br />
<textarea cols="40" name="recaptcha_challenge_field" rows="3"></textarea>
<input name="recaptcha_response_field" type="hidden" value="manual_challenge" />
</noscript>
It appears that the PartialView method is HtmlEncoding the output from the reCaptcha, but not the other form elements that are embedded in the form. Has anyone encountered this or have an elegant solution to this annoying problem that has taken up a couple of hours of my time?
The only solution I've been able to achieve is to render the reCaptcha in the parent view, hide it until the partial view page is called, then relocate it to the appropriate position in the form, which is not a desirable nor elegant solution.
Any help is appreciated.
Thanks.
* UPDATE **
I tried pasting the view code here but stackoverflow's editor kept rejecting the code. Suffice it to say, there is nothing unusual about the view. The model contains properties for binding such as:
[Required]
[Display(Name = "Email Address")]
public string Email { get; set; }
[Required]
[Display(Name = "Confirm Email Address")]
[Compare("Email", ErrorMessage = "Your email and confirmation email do not match.")]
public string ConfirmEmail { get; set; }
The form:
#using (Html.BeginForm("UpdateInfo", "MyAccount", FormMethod.Post, new { #id = "InfoForm" }))
Render the model items:
<div class="editor-label">
#Html.LabelFor(m => m.Email)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.Email) #Html.ValidationMessageFor(m => m.Email)
</div>
Near the end of the form:
<fieldset id="reCaptchaFieldset">
<legend>Captcha Authorization</legend>
#ReCaptcha.GetHtml(theme: "clean", publicKey: System.Configuration.ConfigurationManager.AppSettings["reCaptcha:publicKey"])
</fieldset>
Try the following:
#Html.Raw(Microsoft.Web.Helpers.ReCaptcha.GetHtml(theme: "clean", publicKey: ConfigurationManager.AppSettings["reCaptcha:publicKey"], language: "en"))
Use the AJAX API part in this document:
http://code.google.com/apis/recaptcha/docs/display.html
Use this code in the partialView.

Setting form method to get without specifying controller and action

I have a partial view which I need to re-use:
div class="selectDate">
#using (Html.BeginForm("ViewTransactionLog", "Profile", FormMethod.Get))
{
<div class="selectDateLabel">Date:</div>
<div>
#Html.TextBox("start", range.Start, new { #class = "pickDate" }) to #Html.TextBox("end", range.End, new { #class = "pickDate" })
</div>
<div>
<input type="submit" value="Go" />
</div>
}
</div>
This is the code for picking 2 dates. As the data is lightweight, I wish to pass it through the Get method. I also wish to generalize it and put it into its own cshtml; however, Html.BeginForm expects the controller name and action name to be given if I wish to use the Get method. Is there anyway to avoid this so I could just move the code into a partial view of its own?
Assuming you want the form to post back to the current controller and action, you should be able to use an extension method:
public static MvcForm BeginForm<TModel>(
this HtmlHelper<TModel> html,
FormMethod formMethod)
{
string controller = (string)html.ViewContext.RouteData.Values["controller"];
string action = (string)html.ViewContext.RouteData.Values["action"];
return html.BeginForm(action, controller, formMethod);
}

Resources