Create RouteValueDictionary on server and use in aspx? - ajax

I am tring to pass a RouteValueDictionary to my aspx so that I can use it as the parameters for an Ajax.BeginForm method. I load it up like so:
RouteValues = new System.Web.Routing.RouteValueDictionary();
RouteValues.Add("FindingId", thisFinding.Id);
RouteValues.Add("ReportId", thisFinding.ReportSection.ReportId);
and then add it to my model without issue. When I put it as the parameter to the BeginForm method it renders the action as this:
/SolidWaste/Finding/LoadSection?Count=3&Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D
Here is the aspx code:
(Ajax.BeginForm(Model.FormModel.Action,
Model.FormModel.Controller,
Model.FormModel.RouteValues,
new AjaxOptions {
HttpMethod = "Post",
InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace,
UpdateTargetId = "WindowContent",
}, new { id = FormId })) { %>
<input name="submit" type="submit" class="button" value="" style="float: right;"/>
<% } //End Form %>
Here is the View Model that represents Model.FormModel
public class FormViewModel {
public string Action { get; set; }
public string Controller { get; set; }
public string Method { get; set; }
public RouteValueDictionary RouteValues { get; set; }
}
Any idea why it is not serializing the RouteValueDictionary into the proper URL on the action? I would like to use an object here rather than build the RouteValues by hand with new { field = vale }

Ah, you are using the wrong overload. It's normal. The ASP.NET MVC team really made a mess out of this API. You gotta be careful which method you are invoking. Here's the overload that you need:
<% using (Ajax.BeginForm(
Model.FormModel.Action, // actionName
Model.FormModel.Controller, // controllerName
Model.FormModel.RouteValues, // routeValues
new AjaxOptions { // ajaxOptions
HttpMethod = "Post",
InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace,
UpdateTargetId = "WindowContent",
},
new Dictionary<string, object> { { "id", FormId } }) // htmlAttributes
) { %>
<input name="submit" type="submit" class="button" value="" style="float: right;"/>
<% } %>
Notice the correct overload? You were using the one that was taking routeValues and htmlAttributes as anonymous objects, except that you was passing Model.FormModel.RouteValues as a RouteValueDictionary which basically crapped your overload.
Hit F12 while hovering the cursor over the BeginForm and if you are lucky enough and Intellisense works fine for you in Razor views (which rarely happens) you will get redirected to the method you are actually invoking and realize your mistake.

Related

Partial View not loading once made strongly typed

Controller:
namespace AdminPortal.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public PartialViewResult ServersTab(AdminPortalModel model)
{
return PartialView("~/Views/Home/ServersTab.cshtml", model.Servers);
}
public PartialViewResult _ServerNew()
{
return PartialView("~/Views/Home/_ServerNew.cshtml");
}
}
}
View to be loaded:
#using AdminPortal.CustomHelpers;
#model AdminPortal.Models.AdminPortalModel;
<div id="scrollBox">
This 'div' element uses 'overflow:scroll' to create scrollbars whenever the contents of the 'div' become too large.
</div>
View doing the Loading:
#using AdminPortal.CustomHelpers;
#model IEnumerable<AdminPortal.Models.Server>
...
<div id="NewAndEditButtonWrapper">
#Ajax.ImageActionLink("../../Images/edit_grey.png", "Edit ==>", "_ServerEdit", "",
new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "NewEditSubview"
},
new
{
id = "EditButton"
})
</div>
<div id="NewEditSubview">
</div>
Custom Ajax Helper:
public static IHtmlString ImageActionLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes = null)
{
var builder = new TagBuilder("img");
builder.MergeAttribute("src", imageUrl);
builder.MergeAttribute("alt", altText);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions).ToHtmlString();
return MvcHtmlString.Create(link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)));
}
Essentially, When my "View to be loaded" contains #model AdminPortal.Models.AdminPortalModel; it doesn't load, but when I remove this line it will load. I need this modal so that I can use it in my View to display some information to the user. I am unsure why making the view strongly typed is causing the View not to load. Any advice?
EDIT:
To further expand on "doesn't load":
These errors are impossible to catch because VS never accurately displays errors for me, especially in .cshtml files
You can enable compilation of views in ASP.NET MVC projects. This is disabled by default. The property is MvcBuildViews , and needs to be manually modified in the project file. See for answer: ASP.Net MVC - Compiler Errors in Views

Pass selected item ID into partial view

I am building a page where a user can view the details of an item which s/he selected.
As part of this project, I need to show all the comments that are listed under this particular item using Ajax and partial views.
In the Controller class, I am somehow unable to pass the productID of the selected item to the partial view method. When I hard code the productID into the method, the comments show up, however when I pass it through the parameter, the method won't even trigger.
All the product details, however, show without restrictions.
I would appreciate any help. Below please find the code in my Controller
public ActionResult Index()
{
List<Product> productList = new ProductClient().GetAllProducts().ToList();
return View("Index", productList);
}
//This method works correctly. The id of the product is passed.
public ActionResult Details(int id)
{
return View(new ProductClient().GetProductByID(id));
}
// This method is not even getting triggered.
public PartialViewResult ProductComments(int id)
{
List<Comment> commentList = new ProductCommentClient().GetCommentsByProductID(id).ToList();
return PartialView("_comments", commentList);
}
This is my Details.cshtml
#Ajax.ActionLink("Product Comments", "ProductComments(" + #Model.ID + ")", new AjaxOptions
{
HttpMethod = "Get",
UpdateTargetId= "divComments",
InsertionMode = InsertionMode.InsertAfter
})
<fieldset>
<div id="divComments">
<legend>Comments</legend>
</div>
</fieldset>
Many thanks in advance.
I solved this.
#Ajax.ActionLink("Product Comments", "ProductComments", new {id=Model.ID}, new AjaxOptions
{
HttpMethod = "Get",
UpdateTargetId= "divComments",
InsertionMode = InsertionMode.InsertAfter
})
<fieldset>
<div id="divComments">
<legend>Comments</legend>
</div>
</fieldset>
I was passing the ID in the wrong manner. I hope that this would at least help somebody else.

How to pass checkbox values to controller through ajax in mvc3

I have a property in my class which is of string type.
public string Months { get; set; }
In the view ,I need to create a checkbox list displaying months..
If january is selected 1 should be saved to database.If january and february is selected 1,2 should be saved to database.
I used an ajax form to pass values..It works well for all fields except checkboxlist.
#using (#Ajax.BeginForm("Create", "Rate", null, new AjaxOptions { OnSuccess = "OnSuccessRateCreate", HttpMethod = "POST" }, new { id = "RateForm" }))
{
//fields inside this
#Html.CheckBoxFor(model=>model.Months,new{id="month",value="1"})Jan
#Html.CheckBoxFor(model=>model.Months,new{id="month1",value="2"})Feb
#Html.CheckBoxFor(model=>model.Months,new{id="month2",value="3"})Mar
#Html.CheckBoxFor(model=>model.Months,new{id="month3",value="4"})Apr
}
It shows error:-
Cannot implicitly convert type string to bool.
Pls help...
You have wrong binding. Try to bind the List of this checkboxes
public List<string> Months { get; set; }
#using (#Ajax.BeginForm("Create", "Rate", null, new AjaxOptions { OnSuccess = "OnSuccessRateCreate", HttpMethod = "POST" }, new { id = "RateForm" }))
{
<input type="checkbox" value="0" name="Mounth">
<input type="checkbox" value="1" name="Mounth">
<input type="checkbox" value="2" name="Mounth">
}
works for me

ASP.Net MVC File uploading ViewModel Binding

So I'm fairly new to ASP.net MVC and have been trying to make a fileuploader, but I can't seem to get my uploaded file bound to my viewmodel. I'm trying to apply validation to the uploaded file through my viewmodel which should be doable.
My code:
View:
<div id = "PDFForm">
#using (Ajax.BeginForm("Upload", "Home", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "PDFForm",
},
new { id = "UploadForm", enctype = "multipart/form-data" }))
{
<input type="file" name="Cover" id="Cover" />
<input type="submit" value="Upload"/>
}
</div>
ViewModel:
public class UploadVM
{
[Required]
public HttpPostedFileBase Cover { get; set; }
}
Controlller action:
public ActionResult Upload(UploadVM model)
{
if(ModelState.IsValid() && model.Cover !=null)
{
//do things and return a response view
}
else
{
//return to form
}
}
I've googled around for tutorials and they seem to be able to bind the uploaded file to the viewmodel by using:
enctype = "multipart/form-data"
I can't seem to get it working so I thought you guys might be able to help me out or push me in the right direction.
Thanks in advance!
Edit: I've tried it with HTML.BeginForm() too but that doesn't seem to work either

mvc3 how do I clear the submitted form values

I am new to asp .net mvc3. I am trying to create a failrly simple blog comments section.
I have a CommentsViewModel
public class CommentsViewModel
{
public CommentModel NewComment { get; set; }
public IList<CommentModel> CommentsList { get; set; }
}
The corresponding view is like
<div id="CommentsArea">
#Html.Partial("CommentsList", Model.CommentsList)
</div>
#using (Ajax.BeginForm("Create",
"Comment",
new { id = Model.NewComment.detailsId, comment = Model.NewComment },
new AjaxOptions { UpdateTargetId = "CommentsArea" ,
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace}))
{
<div class="display-label">Add Comment</div>
<div class="display-field">
#Html.EditorFor(model => Model.NewComment.Body)
</div>
<input type="submit" value="Post" />
}
Now when user enters Post button I want the "CommentsArea" to be updated with the new comments list and also the form values to be cleared with empty text.
Here is the Post method:
[HttpPost]
public ActionResult Create(int id, CommentModel newcomment)
{
var newsItem = m_db.NewsList.Single(news => news.Id == id);
if (!string.IsNullOrWhiteSpace(newcomment.Body))
{
newcomment.detailsId = id;
newsItem.Comments.Add(newcomment);
m_db.SaveChanges();
}
return PartialView("CommentsList", newsItem.Comments);
}
Now when user clicks Post button the list gets updated properly,
but the form values are not cleared. i.e. if I posted a comment "New Comments", the comments list gets updated with "New Comments", but that text remains inside the edit box of the form.
How do I clear that text?
just call a js function on success of form submit.
#using (Ajax.BeginForm("Create",
"Comment",
new { id = Model.NewComment.detailsId, comment = Model.NewComment },
new AjaxOptions { OnSuccess="ClearInput", HttpMethod = "Post",}))
on js function render create view again
function ClearInput(){
//call action for render create view
$.ajax({})
}

Resources