Reputation: 328
I am using the following action to save Nav Bar Items edited from with admin of a content management system:
[HttpPost]
public ActionResult aSaveNavs()
{
aLoggedIn();
NavItemsDataContext navDB = new NavItemsDataContext();
Nav n = navDB.Navs.Select(row => row.ID == Convert.ToInt32(Request.Form["ID"]));
n.NavName = Request.Form["NavName"];
n.NavURL = Request.Form["NavURL"];
n.NavEnabled = (Request.Form["NavEnabled"] == "true" ? true : false);
navDB.SubmitChanges();
return Redirect("/Admin/aHome");
}
I am using the following view:
@{
List<Nav> navList = HtmlHelpers.GetNavList();
}
@foreach (Nav item in navList)
{
<tr>
<td style="width: 150px; text-align: center;">
@item.NavName
</td>
<td style="width: 150px; text-align: center;">
<input id="NavName" name="NavName" type="text" value="@item.NavName" />
</td>
<td style="width: 150px; text-align: center;">
<input id="NavURL" name="NavURL" type="text" value="@item.NavURL" />
</td>
<td>
<input id="ID" name="ID" type="text" readonly="readonly" value="@item.ID" />
</td>
</tr>
}
Obviously the view has a few other bits in but this is the section in question.
When I try and save my changes, I get "System.FormatException: Input string was not in a correct format." and the following line is highlighted:
Nav n = navDB.Navs.FirstOrDefault(row => row.ID == Convert.ToInt32(Request.Form["ID"]));
Thanks in advance for any help with this.
Upvotes: 0
Views: 5017
Reputation: 218732
Already people answered how to do the conversion and fixing that error. I will talk about something else.
As SLaks mentioned, you should better consider using the MVC ModelBinding. The MVC team created it for making our life better. So we should take advantage of this nice feature.
Modelbinding depends on strongly typed views. So Let's create a ViewModel
(just a plain class) for your view.
public class NavigationViewModel
{
public int ID { set;get;}
public string Name { set;get;}
public string URL{ set;get;}
public bool IsEnabled{ set;get;}
}
From your GET
action, Create an object of this class and pass it to your View.
public ActionResult aSaveNavs()
{
NavigationViewModel vm=new NavigationViewModel();
return View(vm);
}
Now we will change our View to a strongly typed view.
@model NavigationViewModel
@using(Html.BeginForm())
{
@Html.LabelFor(x=>x.Name)
@Html.TextBoxFor(x=>x.Name)
@Html.LabelFor(x=>x.URL)
@Html.TextBoxFor(x=>x.URL)
@Html.LabelFor(x=>x.IsEnabled)
@Html.CheckBoxFor(x=>x.IsEnabled)
@Html.HiddenFor(x=>x.ID)
<input type="submit" />
}
Now in your POST
action, read the form values from the Properties of our Model/ViewModel
[HttpPost]
public ActionResult aSaveNews(NavigationViewModel model)
{
if(ModelState.IsValid)
{
//Now you will have the Value inside the model Properties
string name=model.Name;
string url=model.URL;
bool isEnabled=model.IsEnabled;
//now save to your Data base and Redirect (PRG pattern)
}
return View(model);
}
Also try to avoid calling your methods inside the View (you are calling the GetNavList
in the view).That appraoch (mixing code and UI) will make your View ugly. One of the main goal of MVC framework is the seperation of concern. So Let us keep the UI and functionality seperate (and clean).
Have an action method for your Listing and get the Items there and pass that to your strongly typed view.
public ActionResult aHome()
{
List<Nav> navList = HtmlHelpers.GetNavList();
return View(navList);
}
And Change View to
@model IEnumerable<Nav>
@foreach (Nav item in navList)
{
<p>@item.Name</p>
}
If you have a single page where you want to update multiple records, consider using EditorTemplates also.
Upvotes: 4
Reputation: 1179
Convert.ToInt32 may still throw an error, for example when it is empty, therefore use this:
int result=0;
Int32.TryParse(Request.Form["ID"].ToString(), out result);
and then in your code:
Nav n = navDB.Navs.FirstOrDefault(row => row.ID == result);
Upvotes: 2
Reputation: 10376
Try to check, if you can convert string to int using int.TryParse
Upvotes: 2