Question

I am unable to make a simple MVC 3 controller/view/model program work with an ActionResult method that includes the Bind attribute with a Prefix property.

One example that I did try could populated the parameter when I call the action method from the URL.

Here is that example controller followed by its view:

//Controller
//public ActionResult PrefixExample(int number = 0)
public ActionResult PrefixExample([Bind(Prefix="okay")]int? number)
{
  return View(number);
}

//View
@model Int32?
@{
  ViewBag.Title = "Example";
}
<h2>Example</h2> 

@using (Html.BeginForm())
{
  if (@Model.HasValue)
  {
    <label>@Model.Value.ToString()</label>
  } else {
    <label>@Model.HasValue.ToString()</label>
  }
  <input type="submit" value="submit" />
}

If I use this url http://localhost/MVCApp/Home/Example?okay=3 the parameter, number, is populated. If I use this url http://localhost/MVCApp/Home/Example?number=3, the parameter isn't populated. Interestingly, with the first url, when I view source, the prefix okay doesn't show up.

If I uncomment the first line of my controller and comment out the second line, the opposite is true: the url with okay won't populate number but the second url using number will populate number in the controller.

I would like to know how to make the following example accept a url and correctly set the "view source" prefix. Here is a possible url http://localhost/MVCApp/Home/SpecificPerson?PersonId=0&FirstName=Joe&LastName=Doe

Note, that if I remove the Bind attribute from the controller method, the above url will work with the MVC app below.

Here is my model/controller/view:

//model:    
namespace MVCApp.Models
{
    public class Person
    {
        [HiddenInput(DisplayValue = false)]
        public int PersonId { get; set; }

        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

//controller
namespace MVCApp.Controllers
{
  public class HomeController : Controller
  {
    public ActionResult SpecificPerson([Bind(Prefix = "myPerson")]Person aPerson)
    {
        return View("SpecificPerson", aPerson);
    }
  }
}

//view
@model MVCApp.Models.Person
@{
  ViewBag.Title = "SpecificPerson";
}
<h2>SpecificPerson</h2>

@Html.EditorForModel();
<br />
@Html.EditorFor(m => m);

I would like to see the above example work. Anyone who could show me why it doesn't work as I expect or what I can do to make it work this way would be greatly appreciated.

Thank you in advance.

Was it helpful?

Solution

I think the EditorForModel brought you a bit off track. If you check the html that is generated by this helper you will see that it's not wrapped in a form. Besides that I think the EditorForModel will not serve you as much as you would like to. You can also get it to work correctly without specifying the Bind prefix.

//model
public class Person
{
 public int Id {get;set;}
 public string FirstName {get;set;}
 public string LastName {get;set;}
}

//controller
public class HomeController : Controller
{
 public ActionResult Index(Person person)
 {
  if("POST".Equals(Request.HttpMethod))
  {
     //for example do some validation and redirect
  }
 return View(person);
 }
}

//view
@model Application.Models.Person //only as example use own

@using(Html.BeginForm("Index","Home", FormMethod.POST))
{

@Html.HiddenFor(x=> x.Id)

  <div>
@Html.LabelFor(x=> x.FirstName)
@Html.TextBoxFor(x=> x.FirstName)
</div>

<div>
@Html.LabelFor(x=> x.LastName)
@Html.TextBoxFor(x=> x.LastName)
</div>

<input type="submit" value="Do a post request"/>
}

Also if you use a url like /Home/Index?Id=9 and you look the HTML code you will see that there will be a element with input type=hidden and the value of 9. You could also use two actionresults to split your logic with [HttpGet] and [HttpPost] as attribute of your Action.

And as last I recommend you to check out the newer versions of MVC; MVC 5 is already out...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top