I'm having a bit of trouble using AJAX action links. Whenever a link is clicked, the UpdateTargetID container is not updated unless the link is clicked twice (which throws an exception on the 2nd click, since the item has already been deleted; after this exception, the page updates).
Also, on the first update, the entire page is reloaded into itself, sort of like an iframe. I have a simple 3 column layout (header, left menu, right content) and the entire web page gets re-rendered in the right content portion. But only once. Subsequent action link clicks do not recursively render the page in itself.
I'm using the following code for an AJAX image link (found here: ASP.NET MVC Ajax.ActionLink with Image):
public static class ImageActionLinkHelper
{
public static string ImageActionLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, object routeValues, AjaxOptions ajaxOptions)
{
var builder = new TagBuilder("img");
builder.MergeAttribute("src", imageUrl);
builder.MergeAttribute("alt", altText);
var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions);
return link.ToString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing));
}
}
This is my action link in .aspx:
<%= Ajax.ImageActionLink("../../content/imgs/delete_icon.png", "Delete error", "Delete", new { id = new Guid(item.ErrorId.ToString()) }, new AjaxOptions { Confirm = "Delete?", UpdateTargetId="errors" }) %>
"errors" is my id to update
[HttpPost]
public ActionResult Delete(Guid id)
{
var error = db.ELMAH_Error.FirstOrDefault(x => x.ErrorId == id);
db.DeleteObject(error);
db.SaveChanges();
return PartialView();
}
You seem to be rendering the whole view. As a result invalid markup would be generated - duplicate body tags etc. Use partial views instead when dealing with Ajax scenarios.
Related
I use a shared layout and I am trying to pass the current location to the logoff method, but I'm not sure how to do it. I've tried: Request.Url.OriginalString, Request.Url.Scheme and in the logoff method the parameter type I put the parameter type as string but it isn't working. Anyone have any idea?
Log Off Button on my layout page
<a onclick="location.href = '#Url.Action("Logoff", "Account", "Request.Url.Scheme")'"><span class="logOffSpan">Sign Out</span
public ActionResult LogOff(string url)
{
var local = Convert.ToBoolean(ConfigurationManager.AppSettings["local"]);
if (local)
{
FormsAuthentication.SignOut();
}
else
{
CasAuthentication.SingleSignOut();
}
Session.Clear();
return to Redirect("Some Method","Some Controller");//I want the user to just return to whatever page they were just on when they clicked log off
}
You can use Request.Url.AbsoluteUri to get the absolute URL of the current page.
Then you can use this overload of #Url.Action method which takes a RouteValueDictionary object as third parameter to build the route params / querystrings.
public virtual string Action (string actionName,
string controllerName,
RouteValueDictionary routeValues);
So your view code will be
<a href="#Url.Action("Logoff", "Account", new { url = Request.Url.AbsoluteUri })">
<span class="logOffSpan">Sign Out</span>
</a>
This will basically generate the anhcor tag with the href attribute value set to /Account/Logogg?url={yourCurrentPageUrl}, where {yourCurrentPageUrl} will be replaced with your current page URL.
Now in your action method you can use the Redirect method with this aboslute URL value which will be available in your url parameter.
public ActionResult LogOff(string url)
{
// Your existing logic
return Redirect(url);
}
I am using Rotativa (version 1.6.3) to generate pdf from my view. I have a simple partial view(_OverallResultPrintVersion.cshtml):
#Styles.Render("~/bundles/css")
<img src="#Url.Action("DrawChart", "Vote", new {area = "Award"})"/>
In my action when returning Rotativa PartialViewAsPdf, it opens an empty pdf page and the "DrawChart" action won't be called as expected.
Here is how I implemented My actions in Vote controller:
public ActionResult OverallResultPdf()
{
return new Rotativa.PartialViewAsPdf(
#"~\Areas\Award\Views\Shared\Widget\_OverallResultPrintVersion.cshtml");
}
public ActionResult DrawChart()
{
var model = getModel();
return PartialView("Widget/_VotesColumnChart", model);
}
When replacing the image source in partial view to an Url, it shows the image but this is not what I'm trying to achieve.
Any idea why Rotativa PartialViewAsPdf cannot call my action from partial view?
PS: there is no authorization restriction for these actions so I don't need to initiate FormsAuthenticationCookieName property when creating PartialViewAsPdf.
here is a workaround to resolve the issue. It costs adding a new Action! (OverallResultPrintVersion) and in OverallResultPdf action, instead of returning PartialViewAsPdf, an ActionAsPdf needs to be returned.
public ActionResult OverallResultPdf()
{
return new Rotativa.ActionAsPdf("OverallResultPrintVersion");
}
public ActionResult OverallResultPrintVersion()
{
return PartialView("Widget/_OverallResultPrintVersion");
}
and DrawChart() action remains untouched.
I have an Edit page and once the form is submitted I'm refreshing the page instead of redirecting the user to the Index page. To do so I'm saving the ID of the item in a temp variable and then use it to redirect the user to the edit page using the temp variable ID. Something like this:
[HttpGet]
public ActionResult Edit(Guid id)
{
TempData["CategoryID"] = id;
Category c = new CategoriesBL().GetCategory(id);
return View(c);
}
[HttpPost]
public ActionResult Edit(Category c)
{
new CategoriesBL().UpdateCategory(c);
return RedirectToAction("Edit", (Guid)TempData["CategoryID"]);
}
That's working fine. However I have two methods in a different form on the same page and whenever I submit either of these two methods the redirection is not working and I'm getting an exception.
One of the methods that's not working:
[HttpPost]
public ActionResult AddNewThumbnail()
{
List<byte[]> thumbs = new List<byte[]>();
for (int i = 0; i < Request.Files.Count; i++)
{
thumbs.Add(ConvertToByteArray(Request.Files[i].InputStream));
}
new CategoriesBL().AddCategoryThumbnail(thumbs, (Guid)TempData["CategoryID"]);
return RedirectToAction("Edit", (Guid)TempData["CategoryID"]);
}
Exception:
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Guid'....
I think it's an issue with routing but the fact is that the same implementation is used and it's working on one form and not the other. I'm not sure whether I'm doing something wrong or if there's any better way to do this.
Note: I have debugged the code several times and the ID I'm passing to the method does have a value in it. However when the page reloads the URL has no ID present.
Debugging
The problem seems to be due to the different forms I'm using. The first form I'm just editing text and it is like so:
#using (Html.BeginForm()) {
// ....
}
In the second form I'm saving and uploading images so the form has to be different
#using (Html.BeginForm("AddNewThumbnail", "Category", FormMethod.Post, new { enctype = "multipart/form-data" })) {
// ....
}
Somehow when I changed the form to the 'normal' one everything worked. But of course I can't use it as I want to save images from this form.
pass the value from your view. Something like this
[HttpPost]
public ActionResult Edit(Category c, FormCollection f)
{
Guid categoryID = (Guid)f["catergoryID"];
new CategoriesBL().UpdateCategory(c);
return RedirectToAction("Edit", catergoryID);
}
In your first example, you have initialisation:
TempData["CategoryID"] = id;
in GET method. So, you have to init your (Guid)TempData["CategoryID"] before you try to access it here:
return RedirectToAction("Edit", (Guid)TempData["CategoryID"]);
Ok so I have an Html.DropDownList and I want to be able to execute a controller method ActionResult output(string test) and send a parameter to it. I have something like this already but I get an Uncaught TypeError: Cannot set property 'action' of null message:
#Html.DropDownList(
"revisions", ViewData["revisions"] as SelectList,
new
{
onchange = "this.form.action = '/Shops/output('test')'; this.form.submit();"
})
How do I go about fixing my code?
If your Action method's parameter name is id,
public ActionResult output(string id)
{
//do something
}
then you may use your form action url like this.(The default routing will take care of rest)
/Shops/output/somestringhere.
If you have a different name, use that as the query string
public ActionResult output(string name)
{
//do something
}
Now use your form action url like
/Shops/output?name=somestringhere
Another suggestion about your code is to avoid Viewdata for rendering the dropdown. Try to use strongly typed view model and it's properties for transfering data to your view. Also try to move your javascript from your view and make it unobutrusive. So that your view stays as clean markup only.
Assuming you want to show a Revision dropdown in a document create view, Add a property to your viewmodel to have the dropdown items.
public class DocumentCreateViewModel
{
//Other properties also here
public List<SelectListItem> Revisions{ set;get;}
public int SelectedRevision { set;get;}
public DocumentCreateViewModel()
{
Revisions=new List<SelectListItem>();
}
}
and in your GET action, fill the dropdown content to the Revisions property.
public ActionResult Create()
{
var vm=new DocumentCreateViewModel();
vm.Revisions=GetRevisionItemsFromSomeWhere();
return View(vm);
}
And in your strongly typed view,
#model DocumentCreateViewModel
#using(Html.Beginform())
{
#Html.DropDownListFor(x => x.SelectedRevision,
new SelectList(Model.Revisions,"Value","Text"), "Select..")
<input type="submit" />
}
Now to handle the form submit on change event of dropdown, add this script.
$(function(){
$("#SelectedRevision").change(function(){
var _this=$(this);
var selectedRevision=_this.val();
$("form#YourFormIDHere")
.attr("action","./Shops/output/"+selectedRevision).submit();
});
});
Instead of hardcoding the url to shops/output, you may use the razor helper method(#Url.Action) to get the proper path.
#Html.DropDownList(
"revisions", ViewData["revisions"] as SelectList,
new
{
onchange = "submitForm();"
})
and your Javacript goes here
function submitForm()
{
var form = document.forms[0];
form = '/Shops/output?test=test';
form.submit();
}
I have a small MVC site that uses the Html.ActionLink helper for a navbar. One thing I would like to change is that the default ActionLink will render out an html link to a page even if that is the current page.
For example, it creates a link like this:
Some title...
even if you're already on /myUrl. It would be nice if it would disable that link and maybe insert a special CSS class to show the currently visited page, like this:
My Url
Some Other Url
This problem must have been encountered before on loads of MVC sites, so I'm curious to know how other people have tackled it.
This seems like a good scenario to roll a custom HTML helper. So let's roll it:
public static class LinkExtensions
{
public static MvcHtmlString MyActionLink(
this HtmlHelper htmlHelper,
string linkText,
string action,
string controller
)
{
var currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
var currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
if (action == currentAction && controller == currentController)
{
var anchor = new TagBuilder("a");
anchor.Attributes["href"] = "#";
anchor.AddCssClass("currentPageCSS");
anchor.SetInnerText(linkText);
return MvcHtmlString.Create(anchor.ToString());
}
return htmlHelper.ActionLink(linkText, action, controller);
}
}
and inside your view:
<%= Html.MyActionLink("hello foo", "Index", "Home") %>
<%= Html.MyActionLink("hello bar", "About", "Home") %>
...
and depending on where you are the helper will generate the proper anchor.