asp.net - una - render partial view mvc 5
MVC 4-Usa un modelo diferente en vista parcial (4)
En su función de [HttpPost]
, si modelstate.isvalid
es falso, usted devuelve su vista de edición, pero necesita definir su pmViewModel
nuevo, de lo contrario su vista parcial no tendrá un objeto para mostrar. Intenta usar lo siguiente y haznos saber lo que sucede
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Profil(ProfileModel model)
{
if (ModelState.IsValid)
{
//insert into database
return Content("everything''s good");
}
else
{
//outputs form errors
var pmViewModel = new ProfileUserViewModel
{
ProfileModelObject = profileModel,
UserModelObject = userModel
};
return View(model);
}
}
Por favor, tengan paciencia con mi noobness , soy súper nuevo en el patrón MVC.
Lo que trato de hacer
Estoy construyendo una página de información de perfil para usuarios registrados en mi sitio. Esta página enumeraría datos sobre el usuario, como la fecha de nacimiento, el número de teléfono, el estado de la suscripción, etc. Obtendrá la idea. También me gustaría tener un formulario para permitir a los usuarios cambiar su contraseña, dirección de correo electrónico, información personal en la misma página .
Mi problema
Los datos del usuario provienen de mi controlador a través de una variable modelo pasada:
public ActionResult Profil()
{
var model = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
return View(model);
}
El resultado se ve así en mi opinión:
<label>Phone number: </label>
@if (Model.PhoneNumber != null)
{
@Model.PhoneNumber
}
else
{
<span class="red">You haven''t set up your phone number yet. </span>
}
La forma en que el usuario podría cambiar su información usaría otro modelo, ProfileModel. Así que, desde mi punto de vista, necesito usar dos modelos, uno para generar información y otro para publicar datos. Pensé que al usar una vista parcial puedo lograr esto, pero obtengo este error:
El elemento de modelo que se pasa al diccionario es del tipo ''Applicense.Models.User'', pero este diccionario requiere un elemento de modelo de tipo ''Applicense.Models.ProfileModel''.
Así es como se ve mi llamada a la vista parcial:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
@Html.Partial("_ModifyProfileInfo")
}
Aquí está la vista parcial:
@model Applicense.Models.ProfileModel
<ul>
<li>
@Html.LabelFor(m => m.Email)
@Html.EditorFor(m => m.Email)
</li>
<li>
@Html.LabelFor(m => m.ConfirmEmail)
@Html.EditorFor(m => m.ConfirmEmail)
</li>
<input type="submit" value="Update e-mail" />
</ul>
Y, finalmente, aquí está mi perfil modelo:
public class ProfileModel
{
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "New e-mail address")]
public string Email { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name = "Confirm new e-mail address")]
[Compare("Email", ErrorMessage = "The e-mail and it''s confirmation field do not match.")]
public string ConfirmEmail { get; set; }
}
¿Me estoy perdiendo de algo? ¿Cuál es la forma correcta de hacer esto?
Editar: Rehice mi código que refleja la respuesta de Nikola Mitev, pero ahora tengo otro problema. Aquí está el error que recibo:
Referencia a objeto no establecida como instancia de un objeto. (@ Model.UserObject.LastName)
Esto solo ocurre cuando estoy publicando los valores modificados de la dirección de correo electrónico. Aquí está mi ViewModel (ProfileModel.cs):
public class ProfileModel
{
public User UserObject { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Új e-mail cím")]
public string Email { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name = "Új e-mail cím megerÅ‘sítése")]
[Compare("Email", ErrorMessage = "A két e-mail cím nem egyezik.")]
public string ConfirmEmail { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name= "E-mail cím")]
public string ReferEmail { get; set; }
}
Controlador:
public ActionResult Profil()
{
var User = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
var ProfileViewModel = new ProfileModel
{
UserObject = User
};
return View(ProfileViewModel);
}
Y finalmente aquí está mi clase de modelo user.cs
:
[Table("UserProfile")]
public class User
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Column("UserName")]
public string UserName { get; set; }
[Column("Email")]
[Required]
public string Email { get; set; }
[Column("FirstName")]
public string FirstName { get; set; }
[Column("LastName")]
public string LastName { get; set; }
[Column("PhoneNumber")]
public string PhoneNumber { get; set; }
... You get the idea of the rest...
Estoy pensando que está sucediendo porque el modelo está tratando de poner datos en cada columna required
en la base de datos.
Edit2: el método de httppost de mi acción de perfil:
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Profil(ProfileModel model)
{
if (ModelState.IsValid)
{
//insert into database
return Content("everything''s good");
}
else
{
//outputs form errors
return View(model);
}
}
Hay una sobrecarga de @Html.Partial
que le permite enviar ViewData
como se define en su controlador: este es el método que generalmente uso para vistas parciales. En su controlador, defina ViewData["mypartialdata"]
como ViewDataDictionary
. Entonces en tu vista
@Html.Partial("_ModifyProfileInfo",ViewData["mypartialdata"])
La mejor forma de manejar esta situación es usar y pasar viewModel a su controlador Profile, viewModel es una clase contenedora para múltiples objetos que quiera pasar a su vista.
public class ProfileUserViewModel
{
public ProfileModel ProfileModelObject {get; set;}
public UserModel UserModelObject {get; set;}
}
Su controlador debería verse así:
public ActionResult Profil()
{
var profileModel = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
var userModel = //fetch from db.
var pmViewModel = new ProfileUserViewModel
{
ProfileModelObject = profileModel,
UserModelObject = userModel
};
return View(pmViewModel);
}
Y finalmente tu punto de vista:
@model Applicense.Models.ProfileUserViewModel
<label>Phone number: </label>
@if (Model.ProfileModelObject.PhoneNumber != null)
{
@Model.PhoneNumber
}
else
{
<span class="red">You haven''t set up your phone number yet. </span>
}
Si bien sé que esta pregunta se ha formulado hace mucho tiempo, algunas personas aún podrían enfrentar un problema similar. Una solución fácil que uso para aprobar o tener más de un modelo de vista en una página es usar un ViewBag para contener el segundo objeto y referirme a él en la vista. Vea el ejemplo a continuación.
En tu controlador haz esto:
Obj2 personalDets = new Obj2();
DbContext ctx = new DbContext();
var details = ctx.GetPersonalInformation;
foreach(var item in details) {
personalDets.Password = item.Password;
personalDets .EmailAddress = item.EmailAddress;
}
ViewBag.PersonalInformation = personalDets;
Entonces, en su opinión, esas propiedades estarán disponibles para usted