I want to show a success message after calling the following ajax.beginform
from Index view
#using (Ajax.BeginForm("Insert", "Home", new AjaxOptions() { UpdateTargetId = "result", HttpMethod = "POST" }))
{
#Html.TextAreaFor(m => m.openion)
}
this is my result div
<div id="result">
</div>
and my controller is
[Httppost]
public ActionResult InforMessage(openionModel usr)
{
return Content("Thanks for adding your openion");
}
but when i try this it is going to another view InforMessage
It is not updating the result div.
There is no Informessage Exist. Still it open a new page with message
"Thanks for adding your openion".How to solve this?
If your redirecting to another page its because you do not have the correct scripts loaded (or have duplicates or have them in the wrong order) so its doing a normal submit.
Ensure you have included (in order)
jquery-{version}.js
jquery.unobtrusive-ajax.js
Related
i use asp.net mvc5. i create a menu in right panel of site (layout). when user click in menu items, load page without refresh page. for to do thisÙˆ i use Ajax.ActionLink.
<aside class="right-panel flexcol">
<button class="accordion">Hotels</button>
<div class="sub-panel flexcol">
#Ajax.ActionLink("View Hotels", "Index", "Hotel", null, new AjaxOptions { HttpMethod = "get", UpdateTargetId = "pageContent" }, new { #class = "sub-menu" })
#Ajax.ActionLink("HotelType", "Index", "HotelType", null, new AjaxOptions { HttpMethod = "get", UpdateTargetId = "pageContent" }, new { #class = "sub-menu" })
</div>
and for call 'New Hotel' page, i use
#Ajax.ActionLink("Create Hotel", "Create", "Hotel", null, new AjaxOptions { HttpMethod = "get", UpdateTargetId = "pageContent" }, new { #class = "bluelink" })
These works properly.
the problem: when i submit Create page, this page send to controller and if model fill a not valid data, page redirect to Create page without layout and css's.
#model ... Models.Hotel
#{
ViewBag.Title = "Create";
Layout =null;
}
controller
public ActionResult Create()
{
return PartialView();
}
[HttpPost]
public ActionResult Create(Hotel model)
{
if (!ModelState.IsValid)
{
return PartialView(model);
}
ApplyToDataBase(model, "uspInsertHotel");
return RedirectToAction("Index");
}
In my opinion, the problem is in that fact that you are returning a partial view in case of invalid model, and this is not an ajax call. I can suggest couple of options, I hope they can help.
First, you can return not a partial view, but the whole view in that case. It probably is not really elegant solution, and it might lead to views duplication.
Another way - to use client-side validation, so you do not have to make a server call to just validate your input. In that case you will probably need to use jQuery validation plugin.
I have spent a lot of time to find a workaround or a solution for the problem that I have. I have an AJAX form like the prototype below:
#using (Ajax.BeginForm("MyAction", "Account", new AjaxOptions() {
HttpMethod = "POST",
UpdateTargetId = Model.MyID.ToString(), OnSuccess = "onSuccess"
}))
{
#Html.AntiForgeryToken()
<fieldset>
<legend></legend>
#Html.HiddenFor(m => m.MyID, new { #id = Model.MyID.ToString() })
}
As you see, the HiddenFor value is updated based on the value that comes from within the POST action like the code snippet below from the POST action:
return Content(model.MyID.ToString());
The good thing is that the AJAX call updates the HiddenFor value but in the next POST action, the value of MyID is zero despite I do know it must be something non-zero!
I read a lot of posts suggesting Model.Clear() or Model.Remove("MyID"), etc. but they even did not help!
What am I doing wrong and what is the firm solution for this? Thanks for the help in advance.
You didn't specify InsertionMode, default is replace. It looks like you replacing hidden input by plain text from controller.
Check Network tab in chrome/firefox developer toolbar during ajax request. There could be also helpful Elements tab to check html after request.
edit:
example:
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test2(Test2Model model)
{
var rnd = new Random();
var random = rnd.Next(10000).ToString();
var response = string.Format("<input id=\"MyID\" name=\"MyID\" type=\"hidden\" value=\"{0}\">", random);
return Content(response);
}
View:
#using (Ajax.BeginForm("Test2", "Form", new AjaxOptions() {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "replaceid"
}))
{
#Html.AntiForgeryToken()
<input type="submit"/>
<div id="replaceid">
#Html.HiddenFor(m => m.MyID)
</div>
}
Regards
I found the solution. I belive that the best and cleanest way is to follow the following article to populate HiddenFor element:
http://slushanthan.blogspot.ca/2013/04/simple-aspnet-mvc-ajax-form-application.html
It neither requires ModelState clean up nor other action-side stuff. It worked well for me.
You might forgot to provide model at GET method in controller,
I dint find answers to this and tried several ways. any help would be appreciated thanks !!
I have view which updates the page without reloading on each click using ajax scripts. Below is the code. but after entire partial views are generated, I want user to redirect complete different view on clicking a link which is not associated to controller user is in now.
my View
#model IMONLP.Models.Search
#{
ViewBag.Title = "Search";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
#using (Ajax.BeginForm("Search", new AjaxOptions() { UpdateTargetId = "results"
}))
{
<br />
#Html.TextBoxFor(m => m.search_text, new { style = "width: 200px;" })
<input type="submit" value="search" />
}
#Ajax.ActionLink("Try Demo", "PLNHK", "PLNHK", new AjaxOptions { })
// this ajax link should redirect to different view,
<div id="results">
#if (!String.IsNullOrEmpty(#Model.search_text))
{
Html.RenderPartial("Searchprocess", Model);
}
</div>
My controller:
public ActionResult Search(Search s)
{
//do something
return PartialView("Searchprocess", s);
}
public ActionResult Selected(Search s)
{
//DO something
return PartialView("Selected", s);
}
The above "TryDEMO" "PLNHK" ajax action link will have to be redirected to new controller and new action and return view thats returned by that action. everytime I click on that, I found it moving to that controller and then to corresponding view but again its getting back to old page. I used #html.actionlink instead of Ajax, but now I get this error
The "RenderBody" method has not been called for layout page "~/Views/PLNHK/PLNHK.cshtml".
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
EDIT : I did create PLNHK.cshtml. while I'm trying to debug this, the control goes to PLNHK controller then to PLNHK view(PLNHK.cshtml) parses each and every step in that page, but finally I would get the output to be the older page. I was thinking may be the Ajax scripts on before page is the reason.
I am new at .NET mvc.
In a view "DisplayThings" I have something like:
#foreach (var thing in Model)
{
#Html.Partial("DisplayPartial", thing)
}
In the partial view "DisplayPartial" I have
#using (Ajax.BeginForm("Afunc", new AjaxOptions ()))
{
#Html.EditorFor(model => model.AstringThing)
#Html.EditorFor(model => model.AintThing)
<input type="submit" name="submit" value="Ajax Post" />
}
At the moment the "Afunc"-Action saves the model to the database and then redirects to a controller action to retrieve all "things" from the database and render the entire "Displaythings" View.
My question is: When i press one of the submitbuttons (There is one submitbutton for every "thing" i the list). I want only that partial view to reload/reflect on my change. I dont want to reload the entire "Displaythings" view. How do I do this? If I just return a partial view I lose everything else but that partial view.
If this is a bad approach please give me directions.
Update:
I am still doing something wrong as I get the partial view rendered in a new page. My controller :
public ActionResult Afunc(ThingModel thingmodel)
{
// do
return PartialView("DisplayPartial", thingmodel);
}
I have tried using UpdateTargetId and onsuccess both with the same result (A new page)
In the AjaxOptions that your are simply now passing as new AjaxOptions you can specify the target element using the UpdateTargetId property:
<div id="unique_thing_id">
#using (Ajax.BeginForm("Afunc", new AjaxOptions { UpdateTargetId = 'unique_thing_id' }))
{
}
</div>
Above, a container with unique id for every "thing" is represented with <div id="unique_thing_id">. This will be replaced with the repsonse of the request. Change Afunc to render only the particular "thing" partial.
I have a delete hyperlink shown on the screen:
UsersPartial VIEW:
<%: Ajax.ActionLink("Delete", "Delete", new { id = item.UserID }, new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "tabs-users", InsertionMode = InsertionMode.Replace }, htmlAttributes: new { data_target = "#tabs-users" })%>
This calls a method in my controller
CONTROLLER
[HttpGet]
public PartialViewResult Delete(int id)
{
userManager.DeleteUser(id);
ViewBag.Status = string.Format("User deleted ok, id: {0}", id);
return PartialView("UsersPartial", userManager.GetUsers());
}
In the above code, I return a PartialView, this works. I would like to also display a message at the top of this view, defined above in ViewBag.Status, but I only want it to show this div once this action is taken.
Also note, that my view I am returning to has is strongly typed:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<LMS.Data.User>>" %>
Lastly, the status message I'd like to display is a div that I created into another partial view so I can show it throughout the site.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<div id="status" class="statusok">
<%: ViewBag.Status %>
</div>
What's the proper way to do this?
ViewBag.Status will be null until you assign a value to it, so you could just do a check for that in your view then display it:
#if(ViewBag.Status != null)
{
<div id="status" class="statusok">
#ViewBag.Status
</div>
}
In subsequent calls that return the same view, simply set ViewBag.Status to null if you no longer wish it to show.
You cannot return 2 different partial views from a controller action. One approach you might use is to render the first partial to a string and then have your controller action return a JSON result with 2 properties - one containing the HTML partial and the other containing the message to display:
[HttpDelete]
public PartialViewResult Delete(int id)
{
userManager.DeleteUser(id);
return Json(new
{
Partial = RenderPartialViewToString("UsersPartial", userManager.GetUsers()),
StatusMessage = string.Format("User deleted ok, id: {0}", id)
});
}
and then:
<%= Ajax.ActionLink(
"Delete",
"Delete",
new {
id = item.UserID
},
new AjaxOptions {
HttpMethod = "DELETE",
OnSuccess = "onDelete"
},
htmlAttributes: new { data_target = "#tabs-users" }
) %>
and then write the onDelete callback:
function onDelete(result) {
$('#tabs-users').html(result.Partial);
// TODO: instead of alerting display the message wherever you want
// and using whatever plugin you want to make it look pretty
alert(result.StatusMessage);
}
You will also notice that I have used the proper HTTP verb for this task - DELETE. Never use the GET verb to invoke controller actions that are modifying state on your server (such as deleting an entity).