MVC - why code after ajax.beginform being executed - asp.net-mvc-4

Form for AJAX call:
#using(Ajax.BeginForm("RefineSearchResults", "Search", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "resultsSec" }))
{
<input type="submit" value="submit" />
<div id="resultsSec"></div>
}
after form tag:
#{Html.RenderAction("Index", "NewsLetter", new { area = "" });}
but, it throws exception on second piece of code when posted back although it's not supposed to be execued because it's an AJAX call and it's outside the Ajax form.
Exception message:
Error executing child request for handler
'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.
Can anyone please tell me what's going wrong here. Thanks!

oops!!! My mistake!
Actually, I was returning the main view again that's why code that wasn't supposed to be rendered was being rendered.
Now I have added the view code that was to be refereshed through Ajax.BeginForm() to a partial view.
My openion:
You should apply Ajax form on partial view preferably because from
controller when you return a view then the target view have to be rendered
again (it's ok when you have to show only a string through Content()
method.)
So, refreshing the partial view through Ajax form would be an ideal way to use Ajax.BeginForm() in my humble openion.

Related

MVC PartialView not rendered when passing strongly typed model

I'm calling a controller method using AJAX request.
This function used to return a partial view so I will load it in an HTML element.
the function:
public PartialViewResult LoadLockTimerEnd()
{
Session["Info"] = new Request();
RequestReply reqRep = new RequestReply("/Home/Index", "ID missing. Reseting");
return PartialView("FailurePartialView", reqRep);
}
When passing a simple string as model to this PartialView it works fine, but when passing a RequestReply object as model it is not working and the partialView is not loaded at all.
The PatialView:
#model EPS_WEB_SITE.Models.RequestReply;
#{
Layout = "~/Views/Shared/_FailureLayout.cshtml";
}
<strong>#Html.Raw(#Model.Message.ToString())</strong>
<div class="buttons-container button-container-small">
<div data-request-url="#Model.RedirectURL.ToString()">
<button type="button" id="dismiss-failure-btn" class="btn btn-danger dismiss">Dismiss</button>
</div>
</div>
The AJAX call:
$.get('/Home/LoadLockTimerEnd', function (data) {
$("#resultDiv").html(data);
});
Why does the PartialView works with string as model and not class as model?
$.ajax({
dataType: "HTML",
url: '/Home/LoadLockTimerEnd',
success: function (data) {
$("#resultDiv").html(data);
}
});
Try to call your Action using this way
OK so I found the problem:
It was a compilation error.
I needed to remove ; in the model binding in the view
#model EPS_WEB_SITE.Models.RequestReply;
I was able to find that in the network tab on Chrome browser.
Double click on the problematic request and it shown the server error.
Hope it will help someone

Pass data from view to controller method

I need to use the name of the current view in a method in my controller
I am able to get the name with the code below in my view.
I will like to pass this #ViewData["pageName"] to my MakeChange action result
in my controller. Each time I step through the MakeChange method all I get
is "object reference not set to an instance of an object"
How can I pass data from my view to controller method ?
#ViewData["pageName"] = #Path.GetFileName(Server.MapPath(VirtualPath))
public ActionResult MakeChange(string lang)
{
string getPageName = ViewData["pageName"].ToString();
return RedirectToAction(getPageName, "Home");
}
You can't pass data from view to controller using ViewData. You can use ViewData to pass data from Controller to your view.
To achieve what you want, you can do as follows:
<input type='hidden' name='lang' value='#Path.GetFileName(Server.MapPath(VirtualPath))' />
<input type='submit' value='send'>
Ps: you should put the input's inside a form tag.
Path.GetFileName(Server.MapPath(VirtualPath)) will give you the razor view name with extension (Ex : index.cshtml). You can not use that with RedirectToAction method as RedirectToAction method is looking for an action method name. You need to trim down the file extension part before using it.
To send this to the controller action, you can keep the value inside a hidden field inside your form. When user posts the form, it will be available in your HttpPost action method. You need to make sure that there is a parameter which has same name as the hidden field's name value.
#using (Html.BeginForm())
{
<input type="text" name="lang" value="English" />
<input type="hidden" name="pageName"
value="#Path.GetFileName(Server.MapPath(VirtualPath))" />
<input id="BtnAdd" type="submit" value="Save" />
}
So your action method will be
public ActionResult MakeChange(string lang,string pageName)
{
var viewName=pageName;
//Get rid of the extension.
viewName = viewName.Replace(".cshtml","");
return RedirectToAction(viewName , "Home");
}
Even if you are doing an ajax post, it will still work, just serialize your form and send it
$("#BtnAdd").click(function(e){
e.preventDefault();
var _this = $(this);
$.post("#Url.Action("MakeChange","Home")",_this.closest("form").serialize(),
function(response){
//do something with response
});
});
There are more clean ways of getting the view name without the file extension trimming approach we did. Take a look at this answer.

Invoke paritcular ActionResult using button click?

When I click on button I need to invoke ResetValues method in controller. But am able to invoke the DocDetails method.
Can anyone help me out!!
#using (Html.BeginForm("DocDetails", "FormAdmin", FormMethod.Get))
{
//some other controls and logic related to that
#{ Html.BeginForm("ResetValues", "FormAdmin", FormMethod.Post);}
<button onclick="location.href='#Url.Action("ResetValues","FormAdmin")'" >Search2</button>
#{ Html.EndForm();}
}
Do not embed one form inside another.
Instead, you can use #Html.ActionLink() to create a link that redirects the user to a different action, then style the link to look like a button:
[Edited to show usage without nesting forms]
#using (Html.BeginForm("DocDetails", "FormAdmin", FormMethod.Get)) {
//some other controls and logic related to that
#Html.ActionLink("Search2", "ResetValues", new {}, new { #class = "button" })
}

Success Alert popup in mvc4 View without using jquery and AJAX

Is it possible to get an alert popup on return to same view after success in mvc4 without using ajax begin form?
I'm trying to submit a form and on success want to show a alert box without using ajax and jquery .
When you submit form, I think then you are redirecting, am i right? So you can use TempData for this purpose:
In controller action:
if(success)
{
TempData["AlertMessage"] = "my alert message";
return RedirectToAction("SomeAction");
}
The view which SomeAction action returns (or in layout view):
#{
var message = TempData["AlertMessage"] ?? string.Empty;
}
<script type="text/javascript">
var message = '#message';
if(message)
alert(message);
</script>
NOTE: If you are not redirecting, but returning view, just use ViewBag instead of TempData.

unobtrusive validation not working with dynamic content

I'm having problems trying to get the unobtrusive jquery validation to work with a partial view that is loaded dynamically through an AJAX call.
I've been spending days trying to get this code to work with no luck.
Here's the View:
#model MvcApplication2.Models.test
#using (Html.BeginForm())
{
#Html.ValidationSummary(true);
<div id="res"></div>
<input id="submit" type="submit" value="submit" />
}
The Partial View:
#model MvcApplication2.Models.test
#Html.TextAreaFor(m => m.MyProperty);
#Html.ValidationMessageFor(m => m.MyProperty);
<script type="text/javascript" >
$.validator.unobtrusive.parse(document);
</script>
The Model:
public class test
{
[Required(ErrorMessage= "required field")]
public int MyProperty { get; set; }
}
The Controller:
public ActionResult GetView()
{
return PartialView("Test");
}
and finally, the javascript:
$(doument).ready(function () {
$.ajax({
url: '/test/getview',
success: function (res) {
$("#res").html(res);
$.validator.unobtrusive.parse($("#res"));
}
});
$("#submit").click(function () {
if ($("form").valid()) {
alert('valid');
return true;
} else {
alert('not valid');
return false;
}
});
The validation does not work. Even if I don't fill any information in the texbox, the submit event shows the alert ('valid').
However, if instead of loading dynamically the view, I use #Html.Partial("test", Model) to render the partial View in the main View (and I don't do the AJAX call), then the validation works just fine.
This is probably because if I load the content dynamically, the controls don't exist in the DOM yet. But I do a call to $.validator.unobtrusive.parse($("#res")); which should be enough to let the validator about the newly loaded controls...
Can anyone help ?
If you try to parse a form that is already parsed it won't update
What you could do when you add dynamic element to the form is either
You could remove the form's validation and re validate it like this:
var form = $(formSelector)
.removeData("validator") /* added by the raw jquery.validate plugin */
.removeData("unobtrusiveValidation"); /* added by the jquery unobtrusive plugin*/
$.validator.unobtrusive.parse(form);
Access the form's unobtrusiveValidation data using the jquery data method:
$(form).data('unobtrusiveValidation')
then access the rules collection and add the new elements attributes (which is somewhat complicated).
You can also check out this article on Applying unobtrusive jquery validation to dynamic content in ASP.Net MVC for a plugin used for adding dynamic elements to a form. This plugin uses the 2nd solution.
As an addition to Nadeem Khedr's answer....
If you've loaded a form in to your DOM dynamically and then call
jQuery.validator.unobtrusive.parse(form);
(with the extra bits mentioned) and are then going to submit that form using ajax remember to call
$(form).valid()
which returns true or false (and runs the actual validation) before you submit your form.
Surprisingly, when I viewed this question, the official ASP.NET docs still did not have any info about the unobtrusive parse() method or how to use it with dynamic content. I took the liberty of creating an issue at the docs repo (referencing #Nadeem's original answer) and submitting a pull request to fix it. This information is now visible in the client side validation section of the model validation topic.
add this to your _Layout.cshtml
$(function () {
//parsing the unobtrusive attributes when we get content via ajax
$(document).ajaxComplete(function () {
$.validator.unobtrusive.parse(document);
});
});
test this:
if ($.validator.unobtrusive != undefined) {
$.validator.unobtrusive.parse("form");
}
I got struck in the same problem and nothing worked except this:
$(document).ready(function () {
rebindvalidators();
});
function rebindvalidators() {
var $form = $("#id-of-form");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse($form);
$form.validate($form.data("unobtrusiveValidation").options);
}
and add
// Check if the form is valid
var $form = $(this.form);
if (!$form.valid())
return;
where you are trying to save the form.
I was saving the form through Ajax call.
Hope this will help someone.
just copy this code again in end of modal code
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
;)