Using MVC3, C#, and the Razor View Engine:
I have a form that has an Ajax Action link. In the options I'm trying to specify OnBegin and OnComplete javascript function calls. In this question, I took out the meat of the functions and simply added alerts so that I could verify that the functions where being hit. What I really want to do with these functions is to use $.blockUI for the duration of the ajax call.
The pertinent code looks like this:
#Ajax.ActionLink("my test link", "myAction", new { Controller = "myController" }, new AjaxOptions { OnBegin = "ajaxStart", OnComplete = "ajaxStop" })
<script type="text/javascript">
function ajaxStart() {
alert("start");
}
function ajaxStop() {
alert("stop");
}
</script>
For some reason, the two functions never get called as specified. I have tried it with and without the parentheses, sucha as this:
#Ajax.ActionLink("my test link", "myAction", new { Controller = "myController" }, new AjaxOptions { OnBegin = "ajaxStart()", OnComplete = "ajaxStop()" })
Neither work.
Any ideas?
Thanks,
Tony
Make sure you have included the following script to your page:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
and that you have enabled unobtrusive ajax in your web.config:
<appSettings>
...
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
In ASP.NET MVC 3 unobtrusive javascript is used with jQuery so uif you don't include the proper scripts, the HTML5 data-* attributes that are emitted by the html helpers are not interpreted and there is no AJAX request being sent.
You can try to put the <script> bloc before the Ajax.ActionLink method call.
Use this syntax for the ajax link:
#Ajax.ActionLink("my test link", "myAction", "myController", new AjaxOptions { OnBegin = "ajaxStart", OnComplete = "ajaxStop" })
and remember to put the import of jquery.unobtrusive-ajax.min.js in your view or in _Layout.cshtml
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Related
This tutorial says:
Note that in a real app, you should generate the URL server-side (via Url.Action call) and pass it down, or use RouteJs rather than hard-coding it. This tutorial hard-codes it for simplicity.
I can't do this in the JS itself:
<CommentBox url="#Url.Action("Comments")" />,
... so what does it mean by "pass it down"?
Is that just another way of saying "define the URL inside a Razor csHtml file where using # is allowed," like this?
<script>
$.CommentsUrl = '#this.Url.Action("Comments", "Home")';
<script>
... or is there a better way?
Even when I do the latter, that doesn't help me get the URL into this piece of code:
ReactDOM.render(
<CommentBox url=??? />,
document.getElementById('content')
);
The following code is actually done in the cshtml razor page. It is rendering the CommentBox component to the content div
ReactDOM.render(
<CommentBox url=??? />,
document.getElementById('content')
);
Since it is in the cshtml you can do this:
<div id="content"></div>
<script type="text/javascript">
ReactDOM.render(
<CommentBox url='#Url.Action("Comments")' />,
document.getElementById('content')
);
</script>
If you are only including a js file then you would need to create a global javascript variable and use it:
CSHTML:
<div id="content"></div>
<script type="text/javascript">
var commentUrl = '#Url.Action("Comments")';
</script>
External JS:
ReactDOM.render(
<CommentBox url={commentUrl} />,
document.getElementById('content')
);
I'm POSTing and trying to re-load a partial view with the new data using Ajax like this:
Index.cshtml
<div id="left-column">
#Html.Partial("~/Views/Project/_ProjectList.cshtml", Model.ProjectList)
</div>
~/Views/Project/_ProjectList.cshtml
#using (Ajax.BeginForm("Create", "Project", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "left-column"
}))
{
<h3>Create a new project</h3>
<div class="form-group">
<label for="new-project-name">Name</label>
<input type="text" class="form-control" id="new-project-name" name="Name" placeholder="Example" />
</div>
<button type="submit" class="btn btn-primary">Create Project</button>
Cancel
}
Then my Controller returns the PartialView after some db work:
[HttpPost]
public PartialViewResult Create(Project newProject)
{
db.Projects.Add(newProject);
db.SaveChanges();
var projectList = db.ProjectLists.SingleOrDefault(pl => pl.Id == 1);
return PartialView("~/Views/Project/_ProjectList.cshtml", projectList);
}
I would expect the _ProjectList partial view to load into the #left-column element with the new projectList passed in by the Controller, but instead, the entire View is being overwritten, so the entire body of the new HTML source looks basically like this:
<body>
<!-- all the stuff from the _ProjectList partial -->
</body>
It's worth noting that after the partial view returns, the URL reads /Project/Create, which I wouldn't expect.
I've included jquery-validate and jquery-validate-unobtrusive, and the console isn't showing any errors, so that shouldn't be the problem.
Any idea what's going on?
When using Ajax.BeginForm helper method to do ajax form posting, you need to include the jquery.unobtrusive-ajax.js file as well. This file has the code to handle the submit button click event and send the form asynchronously rather than doing the normal form submit.
If you do not include this file, the form submit will be normal. My guess is that you missed to include this file and hence missing the ajaxified form submit experience.
So make sure to load this file after jQuery
#Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Here is the link to nuget page if you want to add this file via nuget package manager.
Benjy got it in a comment above. It was a jQuery version issue. I'm running 3.1.0, and jquery.unobtrusive-ajax stopped working with jQuery version 1.9.
I'm using history js, https://github.com/browserstate/history.js/ to and Mvc Partial view, here is my code
In Partial Home
<a id="CreateUser" class="btn btn-primary">Create User </a>
and in my #section scripts to push new url and load partial content in 'state change event'
$('#back').click(function (e) {
History.pushState({ state: 1 }, "Create User", "/System/User/Create/");
});
in contoller there is also logic to load partial view if its ajax call and full view if not, this is to protect from user if they press refresh when in ~/System/User/Create/.
any way my script onClick script in section doesnt work user in /System/User called from Partial View or Ajax, I can solve this by attaching OnClick Event inside outside #section scripts so it became like this:
<a id="CreateUser" class="btn btn-primary">Create User </a>
<script>
$('#back').click(function (e) {
History.pushState({ state: 1 }, "Create User", "/System/User/Create/");
});
</script>
#section scripts
{
<script>
$('#back').click(function (e) {
History.pushState({ state: 1 }, "Create User", "/System/User/Create/");
});
</script>
}
but this is redundant and pain to maintain I know this happend because #section doesnt work with Ajax/Partial, anyway is there's cleaner alternative other than this.
Nevermind findout that '.click' need to be rebind after loading ajax, but with .on('click' there is no need to rebind event handler, so I now just need script on click event in global js.
In my C# MVC4 application, I have two main views: "Index" and "Index_Perm." The logged-in user's role is what determines which of these views is rendered. "Index" contains a view called "PMain" and Index_Perm" contains a view called "PMain_Lim." "PMain" and "PMain_Lim" contain another partial view called "Analysis." Inside of "Analysis", I have this script:
<script type="text/javascript" charset="utf-8">
$(document).ready(function () {
$('#SubmitAverage').click(function () {
var $form = $('#form1');
$.ajax({
type: "POST",
url: "Home/Average",
data: $form.serialize(),
success: function () {
alert("Edit successful");
},
error: function () {
alert('failure');
}
});
});
});
</script>
My issue is that, when "Index" is the main view being accessed this script runs correctly when the Submit button is clicked. When "Index_Perm" is the main view however, when the button is clicked, the AJAX post fails with the error: The resource you are looking for has been removed, had its name changed, or is temporarily unavailable. The directory or file specified does not exist on the Web server. After some investigation in Firebug, I see that it is trying to access: mylocalhost/Home/Index_Perm/Home/Average instead of: mylocalhost/Home/Average which is specified as the url to send the POST in my script.
Here is the applicable portion of code which is identical in "PMain" and "PMain_Lim" which contains the button that is tied to the script:
<div id="Analysis" title="Analysis">
#Html.Action("Analysis", "Home", Model)
</div>
</section>
<section>
<h3>
<button class="btn" id="SubmitAverage" value ="SubmitAverage" name="action:SubmitAverage" type="button">Submit Averages</button>
</h3>
</section>
<section>
<div id="OtherView" title="OtherView" class="OtherChanges">
#Html.Action("OtherView", "Home", (string)ViewBag.SearchKey)
</div>
</section>
Any ideas why its ignoring what I've specified as the URL to use in the JQuery AJAX POST and/or how to correct it?
Use the urlhelper in your ajax post
url: '#Url.Action("Average","Home")',
I am trying to change some data on my page using Ajax. This is a piece of code that does it:
<%= Ajax.ActionLink("Rate Up", "RatePost", new { postId = post.Id, rating = 1 }, new AjaxOptions { UpdateTargetId = string.Format("postRating_{0}", count) })%>
The problem is that RatePost action is not called after click on this link. Instead, the parent view action is being called. How can I avoid this and just call the RatePost action with parameters I specified?
The code seems to be correct.
Verify that you included the Microsoft Ajax scripts in your view:
<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>" type="text/javascript">/script>
<script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.js") %>" type="text/javascript"></script>
If something fails in the javascript generated by Ajax.ActionLink, the click action is not cancelled.