asp.net MVC 3 - JQuery ajax $.get return <nonscript> reCaptcha instead of actual html in partial view - asp.net-mvc-3

This problem is kind of difficult to explain, but I'll do my best.
I'm simply trying to render the reCaptcha input on a form that is embedded inside a partial view.
Here's how I'm obtaining the partial view with JQuery $.get:
GetAndRenderPartialContent: function (url, obj) {
$.get(url, function (data) {
obj.replaceWith(function () {
var content = "<div id=\"" + obj.attr('id') + "\">" + data + "</div>";
return content;
});
});
}
This works great as a JQuery extension method.
The URL that's passed in to this method is simply a controller route that returns a partial view like this:
public ActionResult GetSomeContent()
{
var model = new SomeModel();
// set modal values
// Finally return partial view
return PartialView("_MyPartialView", model);
}
This works great. It even renders form values bound to the model.
The problem is only with reCaptcha. In my view I have this line to render the reCaptcha:
#Microsoft.Web.Helpers.ReCaptcha.GetHtml(theme: "clean", publicKey: ConfigurationManager.AppSettings["reCaptcha:publicKey"], language: "en")
This works when I embed it directly in the parent view.However, when it is rendered from the partial view method, I get the following results:
<noscript>
<iframe frameborder="0" height="300px" src="http://www.google.com/recaptcha/api/noscript?k=[MY PUBLIC KEY REMOVED FOR DEMO]" width="500px"></iframe>
<br /><br />
<textarea cols="40" name="recaptcha_challenge_field" rows="3"></textarea>
<input name="recaptcha_response_field" type="hidden" value="manual_challenge" />
</noscript>
It appears that the PartialView method is HtmlEncoding the output from the reCaptcha, but not the other form elements that are embedded in the form. Has anyone encountered this or have an elegant solution to this annoying problem that has taken up a couple of hours of my time?
The only solution I've been able to achieve is to render the reCaptcha in the parent view, hide it until the partial view page is called, then relocate it to the appropriate position in the form, which is not a desirable nor elegant solution.
Any help is appreciated.
Thanks.
* UPDATE **
I tried pasting the view code here but stackoverflow's editor kept rejecting the code. Suffice it to say, there is nothing unusual about the view. The model contains properties for binding such as:
[Required]
[Display(Name = "Email Address")]
public string Email { get; set; }
[Required]
[Display(Name = "Confirm Email Address")]
[Compare("Email", ErrorMessage = "Your email and confirmation email do not match.")]
public string ConfirmEmail { get; set; }
The form:
#using (Html.BeginForm("UpdateInfo", "MyAccount", FormMethod.Post, new { #id = "InfoForm" }))
Render the model items:
<div class="editor-label">
#Html.LabelFor(m => m.Email)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.Email) #Html.ValidationMessageFor(m => m.Email)
</div>
Near the end of the form:
<fieldset id="reCaptchaFieldset">
<legend>Captcha Authorization</legend>
#ReCaptcha.GetHtml(theme: "clean", publicKey: System.Configuration.ConfigurationManager.AppSettings["reCaptcha:publicKey"])
</fieldset>

Try the following:
#Html.Raw(Microsoft.Web.Helpers.ReCaptcha.GetHtml(theme: "clean", publicKey: ConfigurationManager.AppSettings["reCaptcha:publicKey"], language: "en"))

Use the AJAX API part in this document:
http://code.google.com/apis/recaptcha/docs/display.html
Use this code in the partialView.

Related

partial views to get data and then post the results to save in database

I am very new to MVC, let me try to explain my scenario in plain simple English:
I have an strongly typed mvc form/page (Product.cshtml) with a model, say ProductViewModel.
This page has got two search buttons, one to search and bring the items to be added to the Product and other to bring in the location, most probably partial views.
Now, what I want is that these search results work in ajax form without complete post back, and then the results of these searches (items and location) should be posted back using model binding to the form when user clicks on the submit button.
What could be the best way of achieving this functionality?
Immediate responses will be well appreciated.
I thought, its good to share the complete code for clarity:
I have one form(Service1.chtml) that has a partial view to display users(_TestUser a partial view:read only), then another partial view(_PlotServiceRequestData) that should have a field to search the plot and bring back the details lke its owner name and landuser etc.
Then when I click on submit button of the main form, I should be able to read all data(main form) + new data from _PlotServiceRequestData partial view and save all data to database.
I was trying one more option, that is, to use #Ajax.ActionLink on Service1.cshtml to call the _GetPlotDetails method and then store partial view data in TempData, so that it is available to the form when users clicks on "Submit" button of Service1.cshtml, is this a right approach?, if I use ajax.BeginForm inside partial view then the data is posted to the
Service1 controller method which is actually to save the form data and not to update the partialview and in this method even I am not getting model data of the partial view.
Sevice1.cshtml:
#model ViewModels.TestViewModel
#{
ViewBag.Title =
"Service1";
}
#
using (Html.BeginForm())
{
#Html.LabelFor(m => m.Title)
#Html.EditorFor(m => m.Title)
#Html.Partial(
"_TestUser", Model)
<div id="RequestPlotData">
#Html.Partial(
"_PlotServiceRequestData", Model.requestData)
</div>
<button type="submit">Save Form</button>
}
#section Scripts {
}
_PlotServiceRequestData.cshtml:
===============================
#model ViewModels.PlotServicesRequestDataViewModel
<
div id="RequestPlotData">
#
using (Ajax.BeginForm("_GetPlotDetails", "Test", new AjaxOptions { UpdateTargetId = "RequestPlotData", Url = Url.Action("_GetPlotDetails","Test") }))
{
<h1>Request Details</h1>
 
<div>
#Html.LabelFor(m => m.plotAddress)
#Html.EditorFor(m => m.plotAddress)
<input type="submit" name="submit" value="Ajax Post" />
</div>
<div>
#Html.LabelFor(m => m.LandUser)
#Html.EditorFor(m => m.LandUser)
</div>
<div>
#Html.LabelFor(m => m.OwnerName)
#Html.EditorFor(m => m.OwnerName)
</div>
}
</
div>
CONTROLLER:
==========
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
namespace
TestNameSpace
{
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Service1()
{
Injazat.AM.mServices.
LocalDBEntities context = new Injazat.AM.mServices.LocalDBEntities();
TestViewModel model =
new TestViewModel() { user = context.Users.First(), Title = "Land Setting Out",
requestData =
new PlotServicesRequestDataViewModel() { ServiceNumber ="122345", TransactionDate="10/10/2033" } };
return View(model);
}
[
HttpPost()]
public ActionResult Service1(TestViewModel model)
{
PlotServicesRequestDataViewModel s = (PlotServicesRequestDataViewModel)TempData[
"Data"];
TestViewModel vm =
new TestViewModel() { user = model.user, requestData = s, Title = model.Title };
return View(vm);
 
}
[
HttpGet()]
//public PartialViewResult _GetPlotDetails(string add)
public PartialViewResult _GetPlotDetails(PlotServicesRequestDataViewModel requestData)
{
//PlotServicesRequestDataViewModel requestData = new PlotServicesRequestDataViewModel() { plotAddress = add};
requestData.OwnerName =
"owner";
requestData.LandUser =
"landuser";
TempData[
"Data"] = requestData;
return PartialView("_PlotServiceRequestData", requestData);
}
}
}
You can probably use the jQuery Form plugin for this. This makes the process of posting the data from your form back to the server very easy. The form would post to an action that would return a partial view that you can then push into your UI.
To make this easier, jQuery form actually has a "target" option where it will automatically update with the server response (ie. the partial view returned from your search action).
View
<form id="searchForm" action="#(Url.Action("Search"))" method="POST">
<input name="query" type="text" /> <!-- order use Html.TextBoxFor() here -->
<input type="submit" />
</form>
<div id="result"><!--result here--></div>
Javascript
$('#searchForm').ajaxForm({
target: '#result'
});
Controller
public ActionResult Search(string query)
{
// Do something with query
var model = GetSearchResults(query);
return Partial("SearchResults", model)
}
This should hopefully help you to get on the right track. jQuery Form is a good plugin and is the main thing you should look into for ajaxifying your form posts back to the server. You might also want to look into using jQuery's $.post and $.ajax functions, but these require slightly more work.

MVC3 - list information used for dropdownlist is null after post

I wish to show a DropDownList in a view and therfore include in my model (ExampleAddSetupDto) sent to a view a list of entries to populate the dropdownlist. That works fine, but if I have a validation error and redisplay the view with in incoming model my list is now null.
My Action is given below (note: the problem occurs if ModelState.IsValid fails). Also the Action method second parameter may look odd as I am using Autofac to inject the right service into the method).
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Add(ExampleAddSetupDto add, IServiceAddCommit<IExampleAddSetupDto, IExampleAddCommitDto> service)
{
if (ModelState.IsValid)
{
var response = service.Create(add);
if (response.IsValid)
{
TempData["message"] = "You successfully added a new Example Entry";
return View("AddSuccess", response);
}
//else errors, so copy the errors over to the ModelState
response.CopyErrorsToModelState(ModelState, add);
}
// Some validation error, so redisplay same view
return View(add);
}
My model looks like this:
public class ExampleAddSetupDto : IExampleAddSetupDto
{
[StringLength(50, MinimumLength = 2)]
public string Name { get; set; }
public int Option1Id { get; set; }
public int Option2Id { get; set; }
//-----------------------------
//now the properties for the drop down lists
public IList<Option1> PosibleEntriesForOption1 { get; set; }
public IList<Option2> PosibleEntriesForOption2 { get; set; }
}
My View is:
#model ServiceLayer.Example.DTOs.ExampleAddSetupDto
#{
ViewBag.Title = "Add";
}
<h2>Add</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Add an Example item</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-field">
#Html.Label("Option1")
#Html.DropDownListFor(model => model.Option1Id, new SelectList(Model.PosibleEntriesForOption1, "Option1Id", "OptionText"))
#Html.ValidationMessageFor(model => model.Option1Id)
</div>
<div class="editor-field">
#Html.Label("Option2")
#Html.DropDownListFor(model => model.Option2Id, new SelectList(Model.PosibleEntriesForOption2, "Option2Id", "OptionText"))
#Html.ValidationMessageFor(model => model.Option2Id)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I understand that I need to return the Model.PosibleEntriesForOption in with the form. I tried using the Html.HiddenFor helper in the view to return the list, i.e.
#Html.HiddenFor(model => model.PosibleEntriesForOption1)
but this throws the error
'The value 'System.Collections.Generic.List`1[DataClasses.ExampleClasses.Option1]' is invalid.'.
Clearly I am missing something here and I would appreciate some advice on how to return the lists so that redisplaying the model won't cause an error.
If you are forced to persist the entire list between the two requests, for whatever reason, the best way I see to do this would be to use:
TempData["EnterUniqueKeyHere"] = PossibleEntriesForOption1;
to store it, and then:
PossibleEntriesForOption1 = TempData["EnterUniqueKeyHere"] as IList<Option1>;
to retrieve it.
Note that anything stored in TempData will be removed automatically after a single request.
If the Validation is failing, you need to load up the the dropdownlist with the List of values. Other wise, it will fail.
I believe, when you load up your view initially, it executes HttpGet Method. In HttpGet method you must be binding the Dropdownlist
When you submit page, it executes httpPost method, if all is well, it will submit. If validation fails, it will execute, HTTPPost method, but it cannot find any binding for dropdown.
So try this : In your case
if (ModelState.IsValid)
{
var response = service.Create(add);
if (response.IsValid)
{
TempData["message"] = "You successfully added a new Example Entry";
return View("AddSuccess", response);
}
//else errors, so copy the errors over to the ModelState
response.CopyErrorsToModelState(ModelState, add);
}
else //if validation fails, you need to reload the dropdown and display your view.
{
// populate your dropdown again
// You can add errors list into ModelState.
ViewData.ModelState.AddModelError("What is the error", "Error Message, "What needs to be done by user, to get it work");
return view(add)
}
On the get action for add, you will be creating the model with appropriate values for these 2 properties - PosibleEntriesForOption1 & PosibleEntriesForOption2
Since these are set properly & available on the view, the dropdown gets rendered correctly on the get.
Now on a POST, when validation fails, you have to set those properties again.
if (ModelState.IsValid)
{
// Do something
}
// before you redisplay the same view
// set the properties PosibleEntriesForOption1 & PosibleEntriesForOption2
// Some validation error, so redisplay same view
return View(add);
The TempData technique from Dan Nixon works once but if the validation fails again, the TempData entry is null. I guess I'll have to reload my lists too.

How to keep the same data when return to the view?

How to keep the same data when return to the view?
I tried to put return the form to the view, but it did not work.
Is there any good and simple way to do this?
[HttpPost]
public ActionResult Register(FormCollection form)
{
string name = form["Name"].Trim();
if (string.IsNullOrEmpty(name))
{
TempData["TempData"] = "Please provide your name ";
return View(form);
}
string email = form["Email"].Trim();
var isEmail = Regex.IsMatch(email, #"(\w+)#(\w+)\.(\w+)");
if (!isEmail)
{
TempData["TempData"] = "Sorry, your email is not correct.";
return View(form);
}
//do some things
}
Not sure why you would be using FormCollection in the post but maybe you come from a WebForms background. In MVC you should use ViewModels for the transport of your data to and from the Views.
By default the Register method in an MVC 3 app uses a ViewModel in the Register View. You should simply post it back. In fact, the default app has that already created for you if you didn't know as part of the Internet template.
The standard pattern is to have a ViewModel that represents your data that you will use in your View. For example, in your case:
public class RegisterViewModel {
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
}
Your controller the should contain 2 actions, a Get and a Post. The Get renders the View and is ready for the user to enter data. upon submitting the View the Post action is then called. The View sends the ViewModel to the action and the method then takes action to validate and save the data.
If there is a validation error with the data, it's very simple to return the ViewModel back to the View and display the error messages.
Here is the Get action:
public ActionResult Register() {
var model = new RegisterViewModel();
return View(model);
}
And here is the Post action:
[HttpPost]
public ActionResult Register(RegisterViewModel model) {
if(ModelState.IsValid) { // this validates the data, if something was required, etc...
// save the data here
}
return View(model); // else, if the model had validation errors, this will re-render the same view with the original data
}
Your view would look something like this
#model RegisterViewModel
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Name) <br />
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Email) <br />
#Html.ValidationMessageFor(model => model.Email)
</div>
}
Using other strategies to capture and save data in an MVC app is absolutely possible, it's a very extensible framework. But there is a specific pattern that makes MVC what it is and working against that pattern can sometimes prove difficult. For a beginner it is best to understand the preferred patterns and strategies first and then once understood very well, you can then adopt some of your own custom strategies to meet your needs. By then you should understand the system well enough to know what you need to change and where.
Happy coding!!

MVC3 RemoteAttribute and muliple submit buttons

I have discovered what appears to be a bug using MVC 3 with the RemoteAttibute and the ActionNameSelectorAttribute.
I have implemented a solution to support multiple submit buttons on the same view similar to this post: http://blog.ashmind.com/2010/03/15/multiple-submit-buttons-with-asp-net-mvc-final-solution/
The solution works however, when I introduce the RemoteAttribute in my model, the controllerContext.RequestContext.HttpContext.Request no longer contains any of my submit buttons which causes the the "multi-submit-button" solution to fail.
Has anyone else experienced this scenario?
I know this is not a direct answer to your question, but I would propose an alternative solution to the multiple submit-buttons using clientside JQuery and markup instead:
Javascript
<script type="text/javascript">
$(document).ready(function () {
$("input[type=submit][data-action]").click(function (e) {
var $this = $(this);
var form = $this.parents("form");
var action = $this.attr('data-action');
var controller = $this.attr('data-controller');
form.attr('action', "/" + controller + "/" + action);
form.submit();
e.preventDefault();
});
});
</script>
Html
#using (Html.BeginForm())
{
<input type="text" name="name" id="name" />
<input type="submit" value="Save draft" data-action="SaveDraft" data-controller="Home" />
<input type="submit" value="Publish" data-action="Publish" data-controller="Home" />
}
It might not be as elegant as a code-solution, but it offers somewhat less hassle in that the only thing that actually changes is the action-attribute of the form when a submitbutton is clicked.
Basically what it does is that whenever a submit-button with the attribute data-action set is clicked, it replaces its parent forms action-attribute with a combination of the attributes data-controller and data-action on the clicked button, and then fires the submit-event of the form.
Of course, this particular example is poorly generic and it will always create /Controller/Action url, but this could easily be extended with some more logic in the click-action.
Just a tip :)
i'm not sure that its a bug in mvc 3 as it's not something that you were expecting. the RemoteAttribute causes javascript to intercept and validate the form with an ajax post. to do that, the form post is probably canceled, and when the validation is complete, the form's submit event is probably called directly, rather than using the actual button clicked. i can see where that would be problematic in your scenario, but it makes sense. my suggestion, either don't use the RemoteAttributeand validate things yourself, or don't have multiple form actions.
The problem manifests itself when the RemoteAttribute is used on a model in a view where mutliple submit buttons are used. Regardless of what "multi-button" solution you use, the POST no longer contains any submit inputs.
I managed to solve the problem with a few tweeks to the ActionMethodSelectorAttribute and the addition of a hidden view field and some javascript to help wire up the pieces.
ViewModel
public class NomineeViewModel
{
[Remote("UserAlreadyRegistered", "Nominee", AdditionalFields="Version", ErrorMessage="This Username is already registered with the agency.")]
public string UserName { get; set; }
public int Version {get; set;}
public string SubmitButtonName{ get; set; }
}
ActionMethodSelectorAttribute
public class OnlyIfPostedFromButtonAttribute : ActionMethodSelectorAttribute
{
public String SubmitButton { get; set; }
public String ViewModelSubmitButton { get; set; }
public override Boolean IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
var buttonName = controllerContext.HttpContext.Request[SubmitButton];
if (buttonName == null)
{
//This is neccessary to support the RemoteAttribute that appears to intercepted the form post
//and removes the submit button from the Request (normally detected in the code above)
var viewModelSubmitButton = controllerContext.HttpContext.Request[ViewModelSubmitButton];
if ((viewModelSubmitButton == null) || (viewModelSubmitButton != SubmitButton))
return false;
}
// Modify the requested action to the name of the method the attribute is attached to
controllerContext.RouteData.Values["action"] = methodInfo.Name;
return true;
}
}
View
<script type="text/javascript" language="javascript">
$(function () {
$("input[type=submit][data-action]").click(function (e) {
var action = $(this).attr('data-action');
$("#SubmitButtonName").val(action);
});
});
</script>
<% using (Html.BeginForm())
{%>
<p>
<%= Html.LabelFor(m => m.UserName)%>
<%= Html.DisplayFor(m => m.UserName)%>
</p>
<input type="submit" name="editNominee" value="Edit" data-action="editNominee" />
<input type="submit" name="sendActivationEmail" value="SendActivationEmail" data-action="sendActivationEmail" />
<%=Html.HiddenFor(m=>m.SubmitButtonName) %>
<% } %>
Controller
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Details")]
[OnlyIfPostedFromButton(SubmitButton = "editNominee", ViewModelSubmitButton = "SubmitButtonName")]
public ActionResult DetailsEditNominee(NomineeViewModel nom)
{
return RedirectToAction("Edit", "Nominee", new { id = nom.UserName });
}
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Details")]
[OnlyIfPostedFromButton(SubmitButton = "sendActivationEmail", ViewModelSubmitButton = "SubmitButtonName")]
public ActionResult DetailsSendActivationEmail(NomineeViewModel nom)
{
return RedirectToAction("SendActivationEmail", "Nominee", new { id = nom.UserName });
}
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public ActionResult UserAlreadyRegistered(string UserName, int Version)
{
//Only validate this property for new records (i.e. Version != zero)
return Version != 0 ? Json(true, JsonRequestBehavior.AllowGet)
: Json(! nomineeService.UserNameAlreadyRegistered(CurrentLogonDetails.TaxAgentId, UserName), JsonRequestBehavior.AllowGet);
}
I encountered the same issue.
I also attached an on submit event to prepare the form before submit. Interestingly, when I insert a break point in the on submit function, and then continue, the problem has disappeared.
I ended up with an Ajax form by removing the Remote attribute and validate the field using the ModelState.

UpdateModel not updating the model via ViewModel and property from DropDownListFor

I am trying to set up an Edit view on which I have a text box and DropDownListFor. I have figured out a way to populate the DDLF, and the rendered and posted values are correct, but i cant seem to get the model to update properly.
The object i am trying to update is generated from LINQtoSQL, and in database it has foreign key column. In LINQtoSQL class that resulted in "Contains" relationship. I can get to ID property that represents the column in DB, and also the object that it represents.
zupanija = new Zupanija(); //object that needs to be updated
zupanija.Drzava; //object that i want to change to make the update
zupanija.DrzavaID; //Property linked to object that should change
Only way i have figured out to do the update is to get the value from DDLF and use it to get the object that i want to change like this:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var zupanija = repo.ZupanijaById(id);
var drzava = new repoDrzava().DrzavaById(Convert.ToInt32(collection["Zupanija.DrzavaID"]));
zupanija.Drzava = drzava;
}
Also when i try to update the ID field like this, then i get the folowing error:
zupanija.DrzavaID = Convert.ToInt32(collection["Zupanija.DrzavaID"]);
Error: throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
This seems to me that it is very lousy way to do this, and i am trying to get UpdateModel to work.
I have found the solution while looking for something else, in blog by Joe Stevens:
Using Controller UpdateModel when using ViewModel
The catch is in following: When view model is used then to correctly bind the properties it is necessary to "instruct" the UpdateModel helper how to find the actual class we wish to update.
My solution required to modify
UpdateModel(zupanija); to UpdateModel(zupanija,"Zupanija");
Because i was using a ViewModel class that contained couple properties along with the main data class i wanted to update.
Here is the code, i hope it helps to understand:
public class ZupanijaFVM
{
public IEnumerable<SelectListItem> Drzave { get; private set; }
public Zupanija Zupanija { get; private set; }
...
}
// From Controller
//
// GET: /Admin/Zupanije/Edit/5
public ActionResult Edit(int id)
{
var zupanija = repo.ZupanijaById(id);
return zupanija == null ? View("Error") : View(new ZupanijaFVM(repo.ZupanijaById(id)));
}
//
// POST: /Admin/Zupanije/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var zupanija = repo.ZupanijaById(id);
if (TryUpdateModel(zupanija, "Zupanija"))
{
repo.Save();
return RedirectToAction("Details", new { id = zupanija.ZupanijaID });
}
return View(new ZupanijaFVM(zupanija));
}
//From View:
#model VozniRed.Areas.Admin.Models.ZupanijeFVM
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Zupanija</legend>
#Html.HiddenFor(model => model.Zupanija.ZupanijaID)
<div class="editor-label">
#Html.LabelFor(model => model.Zupanija.Naziv)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Zupanija.Naziv)
#Html.ValidationMessageFor(model => model.Zupanija.Naziv)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Zupanija.Drzava)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Zupanija.DrzavaID, Model.Drzave)
#Html.ValidationMessageFor(model => model.Zupanija.DrzavaID)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
A dropdown list is represented by a <select> tag in an HTML form. A <select> contains a list of <option> tags each containing an ID and a text. When the user selects an option and submits the form the corresponding ID of this options is POSTed to the server. And only the ID. So all you can expect to get in your Edit POST action is the ID of the selected option. And all that UpdateModel does is use the request parameters that are sent and convert them to a strongly typed object. But because all that is a POSTed is a simple ID that's all you can get. From there on you have to query the datastore using this ID if you want to obtain the corresponding model. So you cannot get something that is not existing.

Resources