ModelsState always invalid when using Html.DropDownListFor - asp.net-mvc-3

This is how I create my dropdown
#Html.DropDownListFor(model => model.NewPageModel.AvailablePageModels, new SelectList(Model.NewPageModel.AvailablePageModels, "Text", "Value"))
and this is how my AvailablePageModels looks like
public IEnumerable<SelectListItem> AvailablePageModels
{
get
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in assembly.GetTypes())
{
if (type.GetCustomAttributes(typeof(PageModelAttribute), true).Length > 0)
{
yield return new SelectListItem { Text = type.Name, Value = type.Name };
}
}
}
}
}
and when I post my form to the following action my modelstate is always invalid and the error occur on the AvailablePageModel value? Maybe I cannot use the NewPageModel as a parameter this way?
public ActionResult Create([Bind(Prefix = "NewPageModel")] NewPageModel newPageModel, FormCollection collection)
{
if(ModelState.IsValid) {
// always invalid
}
}

You need 2 fields, one for the available options in the drop down list and one for storing the selected value
Html.DropDownListFor(m => m.NewPageModel.SelectedModel,
new SelectList(Model.NewPageModel.AvailablePageModels, "Text", "Value"))

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 redirect to Details View?

This is my LearnController and here is the create.
[HttpPost]
public ActionResult Create(Learn learn)
{
if (ModelState.IsValid)
{
db.Learns.Add(learn);
db.SaveChanges();
return RedirectToAction("Details", new { id = learn.ModuleId });
}
ViewBag.ModuleId = new SelectList(db.Modules, "ModuleId", "Code", learn.ModuleId);
return View(learn);
}
Here is the detail in my LearnController
public ViewResult Details(int id)
{
var mod = db.Modules.Include("Learns").Single(g => g.ModuleId == id);
return View(mod);
}
In my create view of the learning controller, I place a HTMLActionLink but I can't seem to be redirected. Is there something wrong with my codes?
#Html.ActionLink("Back to List", "Details")
This is the error.
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ViewResult Details(Int32)' in 'Module1.Controllers.LearnController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
The link would need to be #Html.ActionLink("Back to List", "Details", new { id = # }) where # is the id of the Module to display. So when you create a new Learn the GET method would need to be something like
public ActionResult Create(int ID) // ID is the ModuleId your creating the Learn for
{
Learn model = new Learn();
model.ModuleID = ID;
return View(model);
}
and in the view
#model Learn
....
#Html.ActionLink("Back to List", "Details", new { id = Model.ModuleID })
This is assuming that the Details view contains a link to create a new Learn for the Module, where the link would be #Html.ActionLink("Add new Learn", "Create", new { id = Model.ID})
If you can create a new Learn from some other view (where you don't have access to the ID property of Module), and where the view to create a new Learn allows you to select the Module form a drop down list, then you would need javascript/jquery to update the href value of the link based on the selected Module
"The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32", the parameters should be nullable type, change to this
public ViewResult Details(int? id)
{
try
{
if (id.HasValue)
{
var mod = db.Modules.Include("Learns").Single(g => g.ModuleId == id);
if (mod == null)
throw new ArgumentException("Invalid ID");
return View(mod);
}
else
{
throw new ArgumentException("Invalid ID");
}
}
catch (ArgumentException ex)
{
return View(new Modules()); // assumed Details view model is Modules class
}
catch
{
return View(new Modules()); // assumed Details view model is Modules class
}
}
or
public ViewResult Details(string id)
{
try
{
int intId;
if(int.TryParse(id, out intId))
{
var mod = db.Modules.Include("Learns").Single(g => g.ModuleId == intId);
if (mod == null) throw new ArgumentException("Invalid ID");
return View(mod);
}
else
{
throw new ArgumentException("Invalid ID");
}
}
catch (ArgumentException ex)
{
return View(new Modules()); // assumed Details view model is Modules class
}
catch
{
return View(new Modules()); // assumed Details view model is Modules class
}
}
Update
I think I misunderstood your question, all you need to do is change
#Html.ActionLink("Back to List", "Details" })
to
#Html.ActionLink("Back to List", "Details", new { id = Model.ModuleId })
as suggested by Stephen Muecke

Not able to get TermVector results properly in SolrNet

I'm not able to get TermVector results properly thru SolrNet. I tried with the following code.
QueryOptions options = new QueryOptions()
{
OrderBy = new[] { new SortOrder("markupId", Order.ASC) },
TermVector = new TermVectorParameters
{
Fields = new[] { "text" },
Options = TermVectorParameterOptions.All
}
};
var results = SolrMarkupCore.Query(query, options);
foreach (var docVectorResult in results.TermVectorResults)
{
foreach (var vectorResult in docVectorResult.TermVector)
System.Diagnostics.Debug.Print(vectorResult.ToString());
}
In the above code, results.TermVectorResults in the outer foreach gives the proper count whereas docVectorResult.TermVector in the inner foreach is empty.
I've copied the generated solr query of the above code and issued against solr admin and I'm properly getting the termVectors values. The actual query I issued is below
http://localhost:8983/solr/select/?sort=markupId+asc&tv.tf=true&start=0&q=markupId:%2823%29&tv.offsets=true&tv=true&tv.positions=true&tv.fl=text&version=2.2&rows=50
First you should check HTTP query to sure termvector feature is set property.
If it's not OK, change your indexing based on:
The Term Vector Component
If it is OK,You can use "ExtraParams" by changing the handler to termvector handler. Try this:
public SolrQueryExecuter<Product> instance { get; private set; }
public ICollection<TermVectorDocumentResult> resultDoc(string q)
{
string SERVER="http://localhost:7080/solr/core";//change this
var container = ServiceLocator.Current as SolrNet.Utils.Container;
instance = new SolrQueryExecuter<Product>(
container.GetInstance<ISolrAbstractResponseParser<Product>>(),
new SolrConnection(SERVER),
container.GetInstance<ISolrQuerySerializer>(),
container.GetInstance<ISolrFacetQuerySerializer>(),
container.GetInstance<ISolrMoreLikeThisHandlerQueryResultsParser<Product>>());
instance.DefaultHandler = "/tvrh";
SolrQueryResults<Product> results =
instance.Execute(new SolrQuery(q),
new QueryOptions
{
Fields = new[] { "*" },
Start = 0,
Rows = 10,
ExtraParams = new Dictionary<string, string> {
{ "tv.tf", "false" },
{ "tv.df", "false" },
{ "tv.positions", "true" },
{ "tv", "true" },
{ "tv.offsets", "false" },
{ "tv.payloads", "true" },
{ "tv.fl", "message" },// change the field name here
}
}
);
return results.TermVectorResults;
}

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- Radion Button Grouping and Binding from database

How to get the radio button options from database using in MVC3 Razor. I have 4 options for each question, the options should be populated from the database and should be grouped.
#Html.RadioButtonFor(model => Model.AAAa, 'Y', new { title = "Please check this if AAA has been updated" })
Yes
This gives me hard coded value as Yes but text needs to be populated with DB Table.
How would I bind it back the selected value back to the database?. An Example would be more helpful.
Thank you
As always you start by defining a view model that will represent the information you will be dealing with in the view:
public class MyViewModel
{
public string SelectedValue { get; set; }
// In your question you seem to be dealing with a title attribute as well
// If this is the case you could define a custom view model ItemViewModel
// which will contain the Value, the Text and the Title properties for
// each radio button because the built-in SelectListItem class that I am using here
// has only Value and Text properties
public SelectListItem[] Items { get; set; }
}
then you write a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
// Obviously those will come from your database or something
Items = new[]
{
new SelectListItem { Value = "Y", Text = "Yes" },
new SelectListItem { Value = "N", Text = "No" },
new SelectListItem { Value = "D", Text = "Dunno" }
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
then a corresponding view:
#model MyViewModel
#using (Html.BeginForm())
{
for (int i = 0; i < Model.Items.Count; i++)
{
#Html.RadioButtonFor(x => x.SelectedValue, Model.Items[i].Value, new { id = "item_" + i })
#Html.Label("item_" + i, Model.Items[i].Text)
<br/>
}
<button type="submit">OK</button>
}
or to make the view less messy you could write a custom HTML helper that will render those radio buttons for you:
public static class HtmlExtensions
{
public static IHtmlString RadioButtonListFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> items
)
{
var sb = new StringBuilder();
var i = 0;
foreach (var item in items)
{
var id = string.Format("item{0}", i++);
var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id });
var label = htmlHelper.Label(id, item.Text);
sb.AppendFormat("{0}{1}<br/>", radio, label);
}
return new HtmlString(sb.ToString());
}
}
and now your view will simply become:
#model MyViewModel
#using (Html.BeginForm())
{
#Html.RadioButtonListFor(x => x.SelectedValue, Model.Items)
<button type="submit">OK</button>
}
which obviously is nicer to look.

Resources