asp.net mvc add partial view dynamically using ajax - asp.net

I am new to ASP.NET and I have a problem to add a content to my main view. In HtmlBeginform I upload the file on a button click and after file loading I need to display partial view under my main view I donĀ“t know how to call ajax script properly.
My main view:
#using prvniAplikace.Models;
#using Chart.Mvc.ComplexChart;
#using Chart.Mvc.Extensions;
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("LoadFile", "Home", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<div class="form-group" align="left">
<label for="exampleInputFile">Load File</label>
<input type="file" accept=".tcx" class="form-control-file" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
</div>
<div class="form-group" align="left">
<button class="btn btn-primary" type="submit" id="add" name="add" value="Add">Display</button>
</div>
}
#section Scripts {
<script type="text/javascript">
$("#add").on('click', function () {
$.ajax({
async: false,
url: '/Home/getContent'
}).success(function (partialView) {
$('#getContent').append(partialView);
});
});
</script>
}
View I want to add to a main view:
#{
ViewBag.Title = "getContent";
Layout = null;
}
<h2>Obsah</h2>
<p>Odstavec</p>
<p>#DateTime.Now.ToString()</p>
Controller:
namespace prvniAplikace.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
public ActionResult getContent()
{
return PartialView("~/Views/Home/AjaxRequest.cshtml");
}
[HttpPost]
public ActionResult LoadFile(HttpPostedFileBase exampleInputFile)
{
if (exampleInputFile.ContentLength > 0)
{
var fileName = Path.GetFileName(exampleInputFile.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
exampleInputFile.SaveAs(path);
string xmlFile = Server.MapPath(fileName);
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNodeList nodes = doc.GetElementsByTagName("HeartRateBpm");
XmlNodeList nodes2 = doc.GetElementsByTagName("Time");
}
return RedirectToAction("Index");
}
}
}

As per your comment, you would like to load the partial view content via ajax after the index view is (re)loaded after the normal form submit you do to upload the file. To achieve this, you should make the ajax call in the document ready event. Since it is the same page/view user will see before and after the form submit, you should conditionally make the ajax call based on whether the page is loaded for your first GET request or for the GET request issued by the Redirect call in your http post action.
Since Http is stateless, there is no way for the GET action method to know whether this was called from the Redirect method call after successfully processing the submitted form (in your http post action). You may use TempData to address this problem. Before redirecting to the Index view, set a flag to the temp data dictionary which will be available in the next GET request.
[HttpPost]
public ActionResult LoadFile(HttpPostedFileBase exampleInputFile)
{
// your existing code here
TempData["Success"] = true;
return RedirectToAction("Index");
}
Now in your GET action, read this and pass it to view via ViewBag (or a view model property if you have one)
public ActionResult Index()
{
ViewBag.IsSuccess = TempData["Success"];
return View();
}
Now in the view, check this ViewBag item and if it exist and has true value, render the div in which we want to show the partial view content. You can take advantage of the the Url.Action helper method to generate the correct relative path to the action method which returns partial view and keep that in html5 data attribute in the div tag so we can use that in javascript later to make the ajax call.
So add this to your index view.
#if (ViewBag.IsSuccess!=null && ViewBag.IsSuccess)
{
<div data-url="#Url.Action("getContent", "Home")" id="myPartial"> </div>
}
Now all you need is the javascript code which makes the ajax call. Execute that in the document ready event. You can use the jQuery load method.
$(function(){
// Get the url from the data attribute of the div
var url = $("#myPartial").data("url");
// Make the ajax call using load method
$("#myPartial").load(url);
});

Related

Asp.net MVC5 application Runtime compilation

Is there any way to make my asp.net mvc5 applications runtime compilation like angular. In traditional way I change in .cshtml file save and press f5 to refresh running page then I get my change effect on page. But is there any way that can reload my page without pressing f5 in browser as like as angular application do.
Ajax refreshes the current page and gets the data from the server.
As shown in the code: ajax calls the Test action method under the PageLoad controller.
The background code is as follows:
public ActionResult Test()
{
var actionResult = default(JsonResult);
var stu = new STU();
this.UpdateModel(stu);
var tmp = string.Format("{0}{1} old from {2}", stu.Name, stu.Age, stu.City);
actionResult = new JsonResult()
{
Data = new { Message = tmp }
};
Thread.Sleep(5000);
return actionResult;
}
According to the student information passed by the front desk, return a string to ajax.
<form id="student_form">
<input type="submit" id="sub" value="submit" />
</form>
$(document).ready(function() {
$('#student_form').submit(function() {
$.ajax({
// ajax submit code....
});
return false;
});
});

MVC - Update model in view after ajax form submit

I have a question concerning MVC4. I have a form that I submit through ajax to my controller. In the controller, I create a new entry in a database, using the data of the form.
In case of success, the form fields need to go empty and a message should appear that the record has been added. So that the user is ready to add the next item through the form. I can clear the fields in the "ResetView" method through javascript (that's called through "OnSuccess"), that's not a problem
In case of error, the form fields need to remain filled in and a message should appear that it failed. In my case, it calls also the "OnFailure" method "ShowError" (which just shows the div "CustomerMessage").
The issue I am having when an item fails, is that the "CustomMessage" from my model is empty, while I did explicitly set it in my controller. So in my view, the #Model.CustomMessage is always empty!
I read that I should call the "ModelState.Clear()" function in my controller but that doesn't seem to do anything.
Can someone check what could be wrong in my code?
Any help is greatly appreciated.
View:
<div id="createform">
#using (Ajax.BeginForm("Create", "Payment", new { username = User.Identity.Name }, new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "createform",
//OnBegin = "SubmitForm",
OnSuccess = "ResetView",
OnFailure = "ShowError"
}))
{
<div id="CustomMessage">#Model.CustomMessage</div>
... bunch of #Html.TextBoxFor stuff (like below) ...
#Html.TextBoxFor(model => model.SenderName, new { id = "SenderName"})
}
</div>
Controller:
[HttpPost]
public ActionResult Create(PaymentViewModel payment, string username)
{
if (ModelState.IsValid)
{
try
{
paymentRepository.AddPayment(payment.PaymentLine, username);
paymentRepository.SaveChanges();
payment.CustomMessage = "success";
}
catch (Exception ex)
{
payment.CustomMessage = "error";
}
}
else
{
payment.CustomMessage = "error";
}
ModelState.Clear();
return PartialView(payment);
}
I found the problem. It seemed that I was missing a reference to the jquery unobtrusive ajax script. After adding that, everything worked correctly
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

How to save the current model when ajax is requesting?

I'm using Ajax in my application to update a view without refresh the webpage.
Can you notice here http://contoso2.azurewebsites.net/Test/DoTest because I'm highlighting the partial view in yellow color.
But the problem is, when I enter data to the items (math problem), when Ajax is requesting, I don't see the changes in the model.
public ActionResult DoTest()
{
List<Worksheet> worksheets = null;
if (Request.IsAjaxRequest())
{
worksheets = Session["Worksheets"] as List<Worksheet>;
return PartialView("_Problems", worksheets[1]);
}
worksheets = new List<Worksheet>()
{
new Worksheet("Addition and Subtraction of absolute values", new List<Problem1>() { ... }),
new Worksheet("Addition and Subtraction of absolute values", new List<Problem1>() { ... })
}
Session["Worksheets"] = worksheets;
return View(worksheets[0]);
}
I'm using a Session to recover my model, but if I debug in it I don't see any changes of the models. How can I do for when I press continue button, my model updates.
EDIT: This contain my AJAX in razor view
#using (Ajax.BeginForm(
new AjaxOptions
{
HttpMethod = "get",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "problemList"
}))
{
<input type="submit" value="Continue" />
}
I usually have two Actions for a View . Though this is not a mandatory requirement.
The first action decorated with HttpGet renders the page on a Get when the user comes to the page for the first time. the second action is invoked when the user clicks next and posts a form.
public class TestController {
[HttpGet]
public void DoTest(){
var viewModel = new List<Worksheet>()
{
new Worksheet("Addition and Subtraction of absolute values", new List<Problem1>() { ... }),
new Worksheet("Addition and Subtraction of absolute values", new List<Problem1>() { ... })
};
return View(viewModel);
}
[HttpPost]
public void DoTest(List<Worksheet> worksheets){
//do whatever you want with the user response
var response = worksheets[1];
PartialView("_Problems",responseModel);
}
}
Note : you will have to invoke the ajax call with HttpMethod = "post". The ModelBinder in ASP.NET will bind the values posted in the request to your responseModel worksheets
You should try and go over the "getting-started-with-aspnet-mvc4" tutorials available on http://asp.net/

Updating View with Model changes via Ajax Post - MVC3

I am trying to use an Ajax (I think) call to update my model value and then have that new value reflected in the view. I am just using this for testing purposes for the moment.
Here's the overview:
MODEL
public class MyModel
{
public int Integer { get; set; }
public string Str { get; set; }
}
CONTROLLER
public ActionResult Index()
{
var m = new MyModel();
return View("Test1", m);
}
[HttpPost]
public ActionResult ChangeTheValue(MyModel model)
{
var m = new MyModel();
m.Str = model.Str;
m.Str = m.Str + " Changed! ";
m.Integer++;
return View("Test1", m);
}
VIEW
#model Test_Telerik_MVC.Models.MyModel
#using Test_Telerik_MVC.Models
#{
ViewBag.Title = "Test1";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Test1</h2>
#if (false)
{
<script src="~/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery-ui.min.js" type="text/javascript"></script>
}
<h2>
ViewPage1
</h2>
<div>
<input type="button" onclick="changeButtonClicked()" id="changeButton" value="Click Me!" />
<input type="text" value="#Model.Str" class="txt" id="str" name="Str"/>
<div></div>
</div>
<script type="text/javascript">
function changeButtonClicked() {
var url = '#Url.Action("ChangeTheValue", "Test1")';
var data = '#Model';
$.post(url, data, function (view) {
$("#Str").value = '#Model.Str';
});
}
</script>
Basically the view renders a button with a textbox. My sole aim is to simply display the value of my model (Str property) in the textbox.
I have tried various combinations of the changeButtonClicked() function to no avail. Test1 is the name of my controller. What I don't understand is when I debug it, the controller action fires and sets my values correctly. If I place a breakpoint on the "#Model.Str" section of the input tag, it shows me that my #Model.Str is equal to Changed! which is correct. However, as soon as my success function fires in the javascript, the value reverts back to it's original value.
I can make it work by changing the input type to submit and wrapping it in a #Html.BeginForm() section but I am wondering if/how to do it like this? Or is a Submit the only way to accomplish it?
Thanks
First thing in the jQuery the proper way to set a value of an input is to use:
$("#Str").val(#Model.Str);
Next we'll look at the controller. In the POST action result you are returning the entire View in your AJAX call. That means all the HTML, script references, and JavaScript are being returned in your jQuery post request. Since all you are trying to update is the value of the input named Str, I would just return that value as JSON and nothing else.
[HttpPost]
public ActionResult ChangeTheValue(MyModel model)
{
var m = new MyModel();
m.Str = model.Str;
m.Str = m.Str + " Changed! ";
m.Integer++;
return Json(m.Str);
}
Next I would place your HTML inputs in a <form> so you can have jQuery serialize your model for you and then you can change your jQuery post code to be:
function changeButtonClicked() {
var url = '#Url.Action("ChangeTheValue", "Test1")';
$.post(url, $('form').serialize(), function (view) {
$("#Str").val(view);
});
}
All the serialization is doing is encoding the inputs in your form into a string and if everything is named properly ASP.NET will bind that back to your model.
If you need to have your route handle both AJAX calls and full requests you could use ASP.NET's IsAjaxRequest function to test the request and return different results depending on if the request is AJAX or not. You would do something like this in your controller:
[HttpPost]
public ActionResult ChangeTheValue(MyModel model)
{
var m = new MyModel();
m.Str = model.Str;
m.Str = m.Str + " Changed! ";
m.Integer++;
if (Request.IsAjaxRequest) {
return Json(m.Str);
}
else {
return View("Test1", m);
}
}
In the ActionResult above you are doing everything you did before, but now are testing the request type and if it's AJAX you return a JSON result of your string value. If the request was not from an AJAX call then the full View (HTML, scripts, etc) are returned to be displayed in the browser.
I hope this is helps you out and is what you were looking for.
You can update the view, just not the model. The model in a razor page is compiled on the server in order to render the view; you would need to recompile the razor page after every ajax request.
Only real option is to return json from server and manually update DOM/View.

Partial ASP.NET MVC View submit

I'm new in ASP.NET MVC so the question could appear 'stupid', sorry.
I have a Partial View inside my Home view.
The Partial View submit a form calling an Action Method inside the HomeController.
It works fine with server validation, the problem is that after the post only the Partial View is rendered.
How can I render the entire Home view after post?
About the code:
Inside PartialView I have a form:
<% using (Html.BeginForm("Request", "Home")) { %>
Request is a ActionResult defined inside my HomeController.
[HttpPost]
public ActionResult Request(RequestModel model)
{
if (ModelState.IsValid)
{
// Saving data .....
}
else
{
// Show Server Validation Errors
return View();
}
}
At this time, after the post, the ascx shows the server validation erros but only the PartialView ascx code is rendered.
The Url looks like this after the post:
http://xxxxxxxxxxx/Home/Request
What I want is showing the entire Home view with the ascx inside showing server validation errors.
Try to do a partial submit using jQuery:
<script type="text/javascript">
$(document).ready(function () {
$("input[type=submit]").live("click", function () {
var f = $("input[type=submit]").parents("form");
var action = f.attr("action");
var serializedForm = f.serialize();
$.ajax({
type: 'POST',
url: action,
data: serializedForm,
success: function (data, textStatus, request) {
if (!data == "") {
// redisplay partial view
$("#formDiv").html(data);
}
else {
// do whatever on sucess
}
}
});
return false;
});
});
</script>
Assuming your view/ascx/HTML is something like this:
<div id="formDiv">
<% Html.RenderAction("Request"); %>
</div>
Change return type also:
[HttpPost]
public PartialViewResult Request(RequestModel model)
{
if (ModelState.IsValid)
{
// Saving data .....
}
else
{
// Show Server Validation Errors
return PartialView();
}
}
I was facing same issue in code, so I just made a small modification in my code and it worked.
Instead of returning the same view, I used
return Redirect(Request.Referrer)
Earlier:
return View();

Resources