.Net MVC View not rendering - asp.net-mvc-3

I have a Controller listed below:
//
// GET: /Customer/Details/5
public ActionResult Details(short id)
{
ActionResult actionResult = null;
if (HttpContext.User.IsInRole("Admin"))
{
// this is the logic that is getting executed
YeagerTechWcfService.Customer cust = db.GetCustomerID(Convert.ToInt16(id));
actionResult = View("Details", cust); }
else
{
HttpCookie cn = Request.Cookies["strCookieName"];
if (cn != null)
{
YeagerTechWcfService.Customer cust = db.GetCustomerID(Convert.ToInt16(id));
actionResult = View("Details", cust);
}
else
{
TempData["ErrCode"] = "CustView";
actionResult = RedirectToAction("Index", "Home");
}
}
return actionResult;
}
I have a View (where the ActionLink is) like below:
columns.Template(
#<text>
#Ajax.ActionLink("Detail", "Details", "Customer", new { id = item.CustomerID },
new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "detailCustomer" })
</text>
).Width(70);
The rendered output is now as follows:
<a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#detailCustomer" href="/Customer/Details/2">Detail</a>
If I click on the link from within the source view of the browser, I get to my new View just fine.
However, if I try and click on the ActionLink, the View doesn't come up. I can verify during debugging, that I'm stepping thru the Details View after I hit that controller code. The present view just stays in place without switching to the new View.
Moreover, I can see that if I click on the ActionLink, it executes the same exact code (during debugging) as when I paste it into the address bar:
http://localhost:4514/Customer/Details/2
When I click on the ActionLink, even though the same code is executed, the address url doesn't change to the above. and the View is not being rendered.
What am I doing wrong?

even though the same code is executed, the address url doesn't change
to the above
You are using an Ajax.ActionLink meaning that it will send an AJAX request. The whole point of AJAX is to stay on the same page and not redirect.
You indicate UpdateTargetId = "detailCustomer" so make sure that in your page you have a container with this id:
<div id="detailCustomer"></div>
which will be updated with the results of the AJAX call. Also make sure that you have properly included the jquery.unobtrusive-ajax.js script to your page in order for the Ajax.ActionLink helper to do anything useful.
On the other hand if you want to perform a full postback and change the url of your browser you probably need a standard link:
Html.ActionLink("Detail", "Details", "Customer", new { id = item.CustomerID }, null)

Related

AJAX search box in MVC [duplicate]

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

Update div using ajax.beginform inside asp mvc view

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

Adding 'Edit' Ajax.ActionResult to render on same page in MVC

My first ever Ajax request is failing, and I'm not quite sure as to why.
I've used the MVC scaffolding in order to create a table (which uses a default #Html.Actionlink). However, I'm looking to include an 'edit' section on the same page via ajax requests.
So my table now has:
<td>
#Ajax.ActionLink("Edit", "Edit", new { id=item.OID}, new AjaxOptions {
UpdateTargetId = "editblock",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET" }
) |
As suggested here.
Within the same view i have a div defined as:
<div id="editblock">
Edit Section Here
</div>
And My controller is defined as:
public PartialViewResult Edit(int? id)
{
if (id == null)
{
return PartialView(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
}
TableModel tablevar = db.TableModel.Find(id);
if (tablevar == null)
{
return PartialView(HttpNotFound());
}
return PartialView("Edit", tablevar );
}
[HttpPost]
[ValidateAntiForgeryToken]
public PartialViewResult Edit( TableModel tablevar )
{
if (ModelState.IsValid)
{
db.Entry(tablevar ).State = EntityState.Modified;
db.SaveChanges();
}
return PartialView("Edit",tablevar );
}
My "Edit.cshtml" looks like:
#model Project.Models.TableModel
<body>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
Could anyone suggest as to why this is failing, and what I should be doing instead to render this partial view onto the page (as currently it keeps redirecting to new page and not showing on 'index' screen)?
Place those scripts at the bottom of your view. By the time they execute your form isn't present (and therefore the auto-wireup fails). In general, you want <script> tags as close to the </body> tag as possible to your content is there before the script executes.
Other than that, you look fine.

How to display ValidationSummary using multiple forms using MVC

I have looked at many of the solutions on offer on this site and others for my problem but none of them seem to work perfectly for my solution.
On my Layout page I have a login area on the top of the screen. This is always present unless a user is logged in. This login form has a ValidationSummary on it and every time I post back using another form on the site the validation for this login form is being triggered.
I'm almost certain that this is down to how I call this login page from my Layout page. It is not a partial view that is in a Shared folder, it is in an Area in my project. On my Layout page I call the login form like this:
#Html.Action("LogOn", "Account", new { area = "Store" })
The logon page contains the following:
#model Project.ViewModels.LogOn_ViewModel
#{
Layout = null;
}
#using (Ajax.BeginForm("LogOn", "Account", new { #area = "Store" }, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "LoginContainer", LoadingElementId = "actionLoaderImage" }, new { id="LogonForm" }))
{
#Html.AntiForgeryToken()
<div class="loginArea">
<div class="notRegistered">
<h4>Not registered yet?</h4>
Register now<br/>
#Html.ActionLink("Register", "Index", "SignUp", new { area = "Store" }, new { #class = "greenButton" })
</div> <!-- /notRegistered -->
<div class="loginForm">
<div class="formFields">
<label class="inline">#Html.LabelFor(m => m.UserName)</label>
#Html.TextBoxFor(m => m.UserName)
<label class="inline">#Html.LabelFor(m => m.Password)</label>
#Html.PasswordFor(m => m.Password)
<input type="submit" name="LogIn" value="Log in" class="blueButton" />
<img id="actionLoaderImage" src="#Url.Content("~/Content/web/images/loader.gif")" alt="icon" style="margin-right:15px; display:none;" />
#Html.ValidationSummary()
</div>
</div> <!-- /loginForm -->
</div> <!-- /loginArea -->
}
The login controller is standard stuff:
// GET: /Account/Logon
public ActionResult LogOn()
{
// if logged in show logged in view
if (User.Identity.IsAuthenticated)
return View("LoggedIn");
return View();
}
// POST: /Account/Logon
[HttpPost]
public ActionResult LogOn(LogOn_ViewModel model)
{
if (ModelState.IsValid)
{
if (SecurityService.Login(model.UserName, model.Password, model.RememberMe))
{
return View("LoggedIn");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return PartialView(model);
}
I suspect that what is happening here is that Html.Action is 'posting' the login form if a post is occurring elsewhere on the page. This makes sense as the layout page itself would be posted as part of a form post action.
I tried implementing the custom Validator examples from some other SO questions and blogs (http://blogs.imeta.co.uk/MBest/archive/2010/01/19/833.aspx) but I found that using those examples would not display the validation summary with client side validation which is not much use to me.
The solution I am looking for would need to allow both client and server side validations to appear for the correct form. Does anyone have an example of something like this using MVC? I'd like to avoid manually looking after the client side validation using jquery if possible and just to use the framework to handle the work for me.
Thanks for your suggestions,
Rich
After playing around with this issue for longer than I care to admit, the answer as always was simple once you know how!
The solution to this issue for anyone else who comes up against it is to rename your action so your POST action is a different name to your GET action. This way, when the Layout page is posted back and triggers the PartialView to also be posted back there is only a GET action for your PartialView so the ValidationSummary will not be triggered.
Based on my example above I have altered the form to postback to another action for my login partial view and this has solved this issue for me.
In my Layout page the link to the partial in the store area remains the same:
#Html.Action("LogOn", "Account", new { area = "Store" })
The logon form action is then altered to point to a new action - not called the same name as the GET action:
#using (Ajax.BeginForm("ConfirmLogon", "Account", new { #area = "Store" }, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "LoginContainer", LoadingElementId = "actionLoaderImage" }, new { id="LogonForm" }))
{
....
}
Then I just renamed my controller action so that it has a different action name for the POST action so that when the layout page is called using a post and the partial is loaded up with a POST action that it doesn't call my logon POST action:
// POST: /Account/ConfirmLogon
[HttpPost]
public ActionResult ConfirmLogon(LogOn_ViewModel model)
{
if (ModelState.IsValid)
{
if (SecurityService.Login(model.UserName, model.Password, model.RememberMe))
{
return PartialView("LoggedIn");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return PartialView("Logon",model);
}
Hopefully this will help some others out with this issue. Seems so obvious now but drove me nutty :D

MVC3 Ajax.BeginForm odd behavior

I have a very simple view that has a DropDownListFor and a Button inside an Ajax.BeginForm helper. Clicking the button renders the whole view again inside the div I have set to update including the layout page (I also notice a spike in the cpu when clicking the button multiple times)
Here is the Ajax.BeginForm inside the view:
#using (Ajax.BeginForm("About2", "Home", new AjaxOptions { UpdateTargetId = "property22" }))
{
<div>
<div id="property22">
#Html.DropDownListFor(m => m.SomePropertyToBind, new SelectList(Model.list, "property1", "property2"))
</div>
<button type="submit" id="test">
Click me</button>
</div>
}
Any ideas where I'm going wrong?
I uploaded the whole project if someone has a couple of minutes to take a look at it:
http://www.sendspace.com/file/siu3r31 (free provider so there may be a popup)
Thanks
You are using a wrong overload of the Ajax.BeginForm helper. It should be like this:
#using (Ajax.BeginForm(
"About2",
"Home",
null,
new AjaxOptions { UpdateTargetId = "property22" },
new { #id = "refreshe" }
))
Notice the additional null value I am passing as the routeValues parameter. Also in the example you uploaded you forgot to include the TestView.cshtml view. This being said in order to fix the problem you have two possibilities:
Either return a partial view:
public ActionResult About2()
{
Random randomizer = new Random();
int random = randomizer.Next(1, 1000000000);
ModelTest newModelTest = new ModelTest();
string[] stringList = new string[] { "Red", "Blue", "Green" };
newModelTest.list = from test in stringList
select new ModelTestList
{
property1 = test,
property2 = test
};
newModelTest.SomePropertyToBind = stringList[random % 2];
return PartialView("TestView", newModelTest);
}
or disable the layout in the TestView.cshtml view:
#{
Layout = null;
}
Unfortunately from your explanation above and from the code, I am not sure what you are trying to achieve. However, I think your most worry is about having Ajax working in your view.
In your About2 action method, you are trying to return a complete view which is TestView (in that case, it doesnt exist) and passing it the newModelTest view Model. I would advise changing to return either a PartialView or JsonResult.
For example, changing the return statement of About2 action method to
public ActionResult About2()
{
...
return Json(newModelTest);
}
or changing it to a return type to string and returning "TestResult"
public String About2()
{
...
return "TestResult";
}
or you could change the return statement to return a PartialView
Thanks for your replies.
I just realized that About2 should have returned the "About" view instead of the "TestView". I had tried creating a partial view with the Ajax.BeginForm code but I came across the same problem.
This is my first attempt at Ajax.BeginForm (so far I have always used jquery), and I was under the impression that it works in a similar fashion in the sense that by specifying the target id only the contents of that element will get updated, not that the target will actually get replaced by the whole response object.
Thanks for your help, not only did I get it to work, but I now understand how it should work.
I suspect that what's happening is that you're returning the a complete View (including the layout template) in the Ajax response. Try changing your "Home" controller "About2" action temporarily to the following:
public ContentResult About2() {
return Content("Hello World");
}
I tested this sample Action with your Razor markup and clicking the button properly replaced your dropdown list with "Hello World!".
If this is indeed what's happening, then you'll want to return a View from "About2" without the layout by declaring the following at the top of the View that you're returning.
#{
Layout = null;
}

Resources