Action Method Param is always null - asp.net-mvc-3

I can't figure out why when it hits my action method, carFileName is null. I debugged the view and when I iterate through that foreach loop, there is indeed different values in each iteration of that loop for carContent.CarFileName. So for each button when submitted, it should submit the carFileName associated with that particular button.
#if (Model.CarFiles != null && Model.CarnFiles.Count > 0)
{
#foreach (CarContent carContent in Model.CarFiles)
{
using (Html.BeginForm("GetfileDownloadUrl", "Car", FormMethod.Get, new { carId = Model.CarId, userId = Model.UserId, #carFileName = carContent.CarFileName }))
{
#Html.Hidden("userId", Model.UserId);
#Html.Hidden("carId", Model.CarId);
#Html.Hidden("carFileName", carContent.CarFileName);
<p><input type="submit" name="SubmitCommand" value="download" /> #carContent.Name</p>
}
}
}
Here's my action method signature:
[HttpGet]
public string GetFilDownloadUrl(string carFileUrl, int carId, int userId)
{
...
}
Here's the route:
routes.MapRoute("CarDownloadFile", "Cars/{carId}/{userId}/{carFileName}", new { controller = "Car", action = "GetFileDownloadUrl", carnId = UrlParameter.Optional, userId = UrlParameter.Optional, carFileName = UrlParameter.Optional });

Could be because in your route you refer to carFileName, but your action method takes carFileUrl and you carId in your RouteValueDictionary is spelt carnId

Related

DropDownList doesn't pass additional parameter

I would like to pass a number selected from DropDownlist to a GET Create method in other Controller. It looks like:
[HttpGet]
public ActionResult Details(int? id, string error)
{
{...}
var numbers = Enumerable.Range(1, 100);
ViewBag.Quantity = numbers.Select(i => new SelectListItem { Value = i.ToString(), Text = i + "%" });
return View(viewModel);
}
public ActionResult Create(int ID, int quantity)
{
{...}
}
Details View looks like:
<div>
#if (Model.ItemRent.Zatwierdzony == false)
{
using (Html.BeginForm("Create", "ItemRentLists", new { ID = #Model.ItemRent.ItemRentID }, FormMethod.Get))
{
#Html.DropDownList("quantity", new SelectList(ViewBag.Quantity, "Text", "Value"))
<input type="submit" value="Dodaj przedmioty"/>
}
}
</div>
DropDownList doesn't pass a Value to "quantity" parameter in Create method, what is wrong here?
OK I changed #Html.DropDownList("quantity", ViewBag.Quantity as SelectList) and now it works as it should work.

how to register onclick event to #Html.RadioButtonForSelectList in asp.net mvc 3.0

My Model
public class IndexViewModel
{
public IEnumerable<SelectListItem> TestRadioList { get; set; }
[Required(ErrorMessage = "You must select an option for TestRadio")]
public String TestRadio { get; set; }
[Required(ErrorMessage = "You must select an option for TestRadio2")]
public String TestRadio2 { get; set; }
}
public class aTest
{
public Int32 ID { get; set; }
public String Name { get; set; }
}
My Controller
public ActionResult Index()
{
List<aTest> list = new List<aTest>();
list.Add(new aTest() { ID = 1, Name = "Yes" });
list.Add(new aTest() { ID = 2, Name = "No" });
list.Add(new aTest() { ID = 3, Name = "Not applicable" });
list.Add(new aTest() { ID = 3, Name = "Muttu" });
SelectList sl = new SelectList(list, "ID", "Name");
var model = new IndexViewModel();
model.TestRadioList = sl;
return View(model);
}
My View
#using (Html.BeginForm()) {
<div>
#Html.RadioButtonForSelectList(m => m.TestRadio, Model.TestRadioList)
</div>
}
Helper method
public static class HtmlExtensions
{
public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> listOfValues)
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var sb = new StringBuilder();
if (listOfValues != null)
{
// Create a radio button for each item in the list
foreach (SelectListItem item in listOfValues)
{
// Generate an id to be given to the radio button field
var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);
// Create and populate a radio button using the existing html helpers
var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString();
// Create the html string that will be returned to the client
// e.g. <input data-val="true" data-val-required="You must select an option" id="TestRadio_1" name="TestRadio" type="radio" value="1" /><label for="TestRadio_1">Line1</label>
sb.AppendFormat("<div class=\"RadioButton\">{0}{1}</div>", radio, label);
}
}
return MvcHtmlString.Create(sb.ToString());
}
}
Here is the code i'm using... not sure how to give a onclick event for the control. In the helper method i could not find any appropriate htmlattributes parameter. as per my requirement. on click of any radiobutton in the list i need to call a js function with few parameters. which i'm not able to do. Someonce please help. Thanks in advance.
I haven't got the means to test this at the moment, but a rough idea is adding IDictionary htmlAttributes to the method and passing it in there. If you dont have the required onClick code in the view, then you could omit the parameter and do it in the extension method
public static class HtmlExtensions
{
public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> listOfValues,
IDictionary<string, Object> htmlAttributes)
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var sb = new StringBuilder();
if (listOfValues != null)
{
// Create a radio button for each item in the list
foreach (SelectListItem item in listOfValues)
{
// Generate an id to be given to the radio button field
var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);
// Create and populate a radio button using the existing html helpers
var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
htmlAttributes["id"] = id;
var radio = htmlHelper.RadioButtonFor(expression, item.Value, htmlAttributes).ToHtmlString();
// Create the html string that will be returned to the client
// e.g. <input data-val="true" data-val-required="You must select an option" id="TestRadio_1" name="TestRadio" type="radio" value="1" /><label for="TestRadio_1">Line1</label>
sb.AppendFormat("<div class=\"RadioButton\">{0}{1}</div>", radio, label);
}
}
return MvcHtmlString.Create(sb.ToString());
}
}
and then call it using something like:
#Html.RadioButtonForSelectList(m => m.TestRadio, Model.TestRadioList, new { onclick="someFunction();" })
alternatively you could set a css class and bind to the click event. for example,
<script type="text/javascript>
$('.someClassName').click( function() {
alert('clicked');
});
</script>
#Html.RadioButtonForSelectList(m => m.TestRadio, Model.TestRadioList, new { #class="someClassName" })

MultiSelectList does not highlight previously selected items

In a ASP.NET MVC (Razor) project, I'm using a ListBox with Multi Select option in a Edit View,
CONTROLLER
public ActionResult Edit(int id)
{
Post post = db.Posts.Find(id);
string selectedValues = post.Tags; //This contains Selected values list (Eg: "AA,BB")
ViewBag.Tagslist = GetTags(selectedValues.Split(','));
return View(post);
}
private MultiSelectList GetTags(string[] selectedValues)
{
var tagsQuery = from d in db.Tags
orderby d.Name
select d;
return new MultiSelectList(tagsQuery, "Name", "Name", selectedValues);
}
HTML
<div class="editor-field">
#Html.ListBox("Tags", ViewBag.Tagslist as MultiSelectList)
</div>
This loads the items (Tag List) in to ListBox, but does not highlight the items in the Selected Values list.
How to fix this issue?
Thanks in advance.
I suspect that your Post class (to which your view is strongly typed) has a property called Tags. You also use Tags as first argument of the ListBox helper. This means that the helper will look into this property first and ignore the selected values you passed to the MultiSelectList. So the correct way to set a selected value is the following:
public ActionResult Edit(int id)
{
Post post = db.Posts.Find(id);
ViewBag.Tagslist = GetTags();
return View(post);
}
private MultiSelectList GetTags()
{
var tagsQuery = from d in db.Tags
orderby d.Name
select d;
return new MultiSelectList(tagsQuery, "Name", "Name");
}
and in the view:
<div class="editor-field">
#Html.ListBoxFor(x => x.Tags, ViewBag.Tagslist as MultiSelectList)
</div>
And here's a full example that should illustrate:
public class HomeController : Controller
{
public ActionResult Index()
{
var post = new Post
{
Tags = new[] { "AA", "BB" }
};
var allTags = new[]
{
new { Name = "AA" }, new { Name = "BB" }, new { Name = "CC" },
};
ViewBag.Tagslist = new MultiSelectList(allTags, "Name", "Name");
return View(post);
}
}
Also I would recommend you using view models instead of passing your domain entities to the view. So in your PostViewModel you will have a property called AllTags of type MultiSelectList. This way you will be able to get rid of the weak typed ViewBag.

MVC3 Areas routing conflict

Question: i want my route to be like that
/admin/main/category/1 -> 1 == ?page=1
i don't want page=1 to be seen
My Controller
public class MainController : BaseController
{
private const int PageSize = 5; //pager view size
[Inject]
public ICategoryRepository CategoryRepository { get; set; }
public ActionResult Index()
{
return View();
}
public ActionResult Category(int page)
{
//int pageIndex = page.HasValue ? page.Value : 1;
int pageIndex = page != 0 ? page : 1;
return View("Category", CategoryViewModelFactory(pageIndex));
}
/*
*Helper: private instance/static methods
======================================================================*/
private CategoryViewModel CategoryViewModelFactory(int pageIndex) //generate viewmodel category result on pager request
{
return new CategoryViewModel
{
Categories = CategoryRepository.GetActiveCategoriesListDescending().ToPagedList(pageIndex, PageSize)
};
}
}
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRouteLowercase(
"AdminCategoryListView",
"admin/{controller}/{action}/{page}",
new { controller = "Category", action = "Category", page = "1" },
new { id = #"\d+" },
new[] { "WebUI.Areas.Admin.Controllers" }
);
}
}
My Exception:
The parameters dictionary contains a null entry for parameter 'page'
of non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult Category(Int32)' in
'WebUI.Areas.Admin.Controllers.MainController'. An optional parameter
must be a reference type, a nullable type, or be declared as an
optional parameter. Parameter name: parameters
Thank you all in advance.
Make sure that in your Admin area route registration you have defined the {page} route token instead of {id} which is generated by default:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{page}",
new { action = "Index", page = UrlParameter.Optional }
);
}
Now when you are generating links make sure you specify this parameter:
#Html.ActionLink(
"go to page 5", // linkText
"category", // actionName
"main", // controllerName
new { area = "admin", page = "5" }, // routeValues
null // htmlAttributes
)
will emit:
go to page 5
and when this url is requested the Category action will be invoked and passed page=5 parameter.

ASP.NET MVC 3 WebGrid, preserve the paging and define the route

I am start to learn the MVC3, But i have some problem on WebGrid,
The Controller name is TestController, so i navigate to :
http://localhost:53503/Test/
And the Webgrid shown as below:
two column : ID and Name.
the 3rd & 4th column : Actionlink and item.GetSelectLink.
The first problem is :
Assume i viewing page 3 of webgrid, and press the ActionLink,after go-thought the TestContoller's Action, the webgrid will return to page 1 after PostBack.
However,if i press the [View(GetSelectLink)] on right end:
(e.g. http://localhost:53503/Test/?gridItems_page=3&gridItems_selectedRow=3
It works.
So, i should use ActionLink or GetSelectLink for general Add/Update/Delete operation?
MVC3 hasn't viewstate / control state, so how can i preserve the current page selection after PostBack?
The second problem is :
The (href) of ActionLink is :
http://localhost:53503/Test/GetSelection/7?Name=PSP
I would make it to
http://localhost:53503/Test/GetSelection/7/PSP
I add a new route to global.asax, but it is no luck.
Thanks you very much for help.
It is my code:
Views/Test/Index.cshtml
#model List<MvcContract.Controllers.Products>
#{
System.Web.Helpers.WebGrid grid = new System.Web.Helpers.WebGrid(
source: Model,
canPage: true,
rowsPerPage: 3,
fieldNamePrefix: "gridItems_",
pageFieldName: "page",
selectionFieldName: "selectedRow"
);
}
#{
if (Model != null)
{
#grid.GetHtml(
columns: grid.Columns(
grid.Column("ID"),
grid.Column("Name"),
grid.Column(format: (item) => Html.ActionLink("View(ActionLink)", "GetSelection", new { ID = item.ID, Name = item.Name })),
grid.Column(format: (item) => item.GetSelectLink("View(GetSelectLink)"))
)
);
}
}
Controllers/TestController.cs
namespace MvcContract.Controllers
{
public class Products
{
public string ID { get; set; }
public string Name { get; set; }
public List<Products> GetItems()
{
List<Products> items = new List<Products>();
items.Add(new Products() { ID = "1", Name = "PS3" });
items.Add(new Products() { ID = "2", Name = "XBox360" });
items.Add(new Products() { ID = "3", Name = "Wii" });
items.Add(new Products() { ID = "4", Name = "Saturn" });
items.Add(new Products() { ID = "5", Name = "Dreamcast" });
items.Add(new Products() { ID = "6", Name = "NDS" });
items.Add(new Products() { ID = "7", Name = "PSP" });
items.Add(new Products() { ID = "8", Name = "NeoGeo" });
items.Add(new Products() { ID = "9", Name = "3DO" });
items.Add(new Products() { ID = "10", Name = "Playdia" });
return items;
}
}
public class TestController : Controller
{
//Bind data to WebGrid
public ActionResult Index()
{
Products products = new Products();
return View(products.GetItems());
}
//Some Logic
public ActionResult GetSelection(string ID, string Name)
{
string SelectedID = ID;
return RedirectToAction("Index");
}
}
}
RegisterRoutes() in Global.asax.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Test_GetSelection", // Route name
"{controller}/{action}/{id}/{name}", // URL with parameters
new { controller = "Test", action = "GetSelection", id = UrlParameter.Optional, name = UrlParameter.Optional } // Parameter defaults
);
}
Check out this discussion. I think one of several solutions there may solve your issue.
Since its been a whole year since you posted this, please post an answer if you figured it out another way.

Resources