2011-03-17 23 views
8

Tengo una entidad llamada Domain.Models.BlogPost que contiene las siguientes propiedades:ASP.NET MVC 3 campos-modelo de unión y forman

  • postID
  • Título
  • Autor
  • PostedDate
  • cuerpo

También tengo una entidad llamada Domain.Models.PostComment que contiene las siguientes propiedades:

  • CommentID
  • PostID
  • Autor
  • correo electrónico
  • sitio web
  • cuerpo

BlogPost contiene muchos PostComments. Una relación de uno a muchos.

ahora tengo una vista como esta (formulario de comentarios separados de código de entrada de blog a través de comentario HTML):

@model Domain.Models.BlogPost 
@using Domain.Models; 
@{ 
    ViewBag.Title = "Post"; 
} 
<div class="postTitle">@Model.Title</div> 
<div class="subInfo"> 
    Posted by @Model.Author on @Model.PostedDate.ToString("D") 
</div> 
<div class="postBody"> 
    @Html.Markdown(Model.Body) 
</div> 
<br /> 
@Model.PostComments.Count Comment(s). 
<div class="comments"> 
@foreach (PostComment postComment in Model.PostComments) 
{ 
    Html.RenderPartial("PostComment", postComment); 
} 
</div> 

<!-- BELOW IS THE ADD COMMENT FORM --> 

<div id="addComment"> 
@using (Html.BeginForm("AddComment", "Blog")) 
{ 
    <text> 
    @Html.Hidden("PostID", Model.PostID)<br /> 
    Name: @Html.TextBox("Author")<br /> 
    Email: @Html.TextBox("Email")<br /> 
    Website: @Html.TextBox("Website")<br /> 
    Body: @Html.TextArea("Body")<br /> 
    <input type="submit" value = "Add Comment" /> 
    </text> 
} 
</div> 
@Html.ActionLink("Add Comment", "AddComment") 

El problema es que debido a que el formulario de comentarios utiliza @Html.TextBox("Author") y @Html.TextBox("Body"), que se rellena con datos de el modelo, que también contiene las propiedades Author y Body. ¿Alguna sugerencia sobre cómo solucionar esto para que estos campos no obtengan valores cuando se carga la página?

También probé la creación de un BlogPostViewModel y establecer que a medida que el modelo de la vista y la asignación de la propiedad BlogPost con mi modelo real:

public class BlogPostViewModel 
{ 
    public BlogPost BlogPost { get; set; } 
    public PostComment NewComment { get; set; } 
} 

luego hice @Html.TextBoxFor(x => x.NewComment.Author) pero cuando el formulario enviado a este método de acción:

public ActionResult AddComment(PostComment postComment) 
{ 
    // ... 
} 

postComment no se unió a los valores de la forma:/

+3

Este es un hecho desagradable del encuadernador de modelo predeterminado. He golpeado esto algunas veces. Mi mejor solución ha sido agregar [Bind (Exclude = "Author, Body")] a la acción y luego arreglar el snafu manualmente. Me encantaría escuchar un mejor enfoque. –

+0

Me encantaría escuchar un mejor enfoque también. – Chev

+0

Vio su actualización, intente vinculante según el prefijo NewComment. es decir, poner [Bind (Prefix = "NewComment")] antes del parámetro PostComment postComment –

Respuesta

6

Puede cambiar el nombre de los campos en la sección AddComment a algo que no colisione con las propiedades nombradas en el Modelo, o puede anular el valor en la vista usando una sobrecarga diferente de Html.TextBoxThis overload of TextBox takes a value:

valor (Tipo: System.Object)
el valor del elemento de entrada de texto. Si este valor es nulo, el valor del elemento se recupera del objeto ViewDataDictionary. Si no existe ningún valor allí, el valor se recupera del objeto ModelStateDictionary.


ACTUALIZACIÓN: Desde que agregó "NewComment" como una propiedad y resolvió la propiedad nombrar colisión de esa manera, todo lo que necesita hacer para enlazar un PostComment lugar de todo el modelo de vista de POST a la acción , es instruir a la carpeta modelo que se usará un prefijo. Esto se hace usando el BindAttribute.

public ActionResult AddComment([Bind(Prefix = "NewComment")] PostComment postComment) 
+0

Hmmm, está bien, son dos personas que me dicen que anule el valor de 'string.Empty' así que supongo que eso es lo que haré. Solo pensé que habría una mejor manera de estructurar los modelos/vistas para que estas colisiones ni siquiera ocurran. – Chev

+0

Puede estructurarlo de una manera diferente para evitar la colisión. @Jakub Konecki está en el camino correcto. Agregue una propiedad PostComment denominada "NewComment" a la clase de modelo BlogPost. Entonces su código de vista se vería como @ Html.TextBoxFor (x => x.NewComment.Body); –

+0

a la derecha, excepto entonces tengo que aceptar el modelo de vista como un parámetro en el método de acción 'AddComment', en lugar de aceptar un simple objeto' PostComment'. Como mencioné en la pregunta, probé esto una vez. – Chev

0

Es no hay una sobrecarga en TextBox que toma un valor? Simplemente podría pasar string.Empty ...

+0

Sí, pero esto parece hackish. Se siente como si hubiera una mejor manera. – Chev

+0

Pero creo que quiere el valor que pone el usuario. El valor del usuario se ve afectado por la carpeta de modelo predeterminada después de que se produce la POST. –

+0

Creo que esta es una forma adecuada: desea presentar un formulario vacío. Podría enlazar a una instancia vacía de PostComment ... –

1

Utilice las plantillas ASP NET MVC para que tenga un control total sobre lo que se rellena y es seguro para el tipo.

Así que crearía una plantilla .ascx que toma un Comment fuertemente tipado. En tu modelo, dejas uno vacío allí.

+0

¿No significaría esto que el método de acción 'AddComment' tendría que aceptar' BlogPostViewModel' como un parámetro en lugar de solo 'PostComment'? Parece extraño publicar un objeto de modelo de vista con todas las propiedades vacías, excepto la que estoy buscando. Tal vez estoy equivocado y eso es totalmente normal. – Chev

+0

No. Pasaría 'Model.EditorFor (m => m.Comment)' – Aliostad

+0

En la vista sí, pero el método de acción requeriría aceptar un objeto de modelo de vista, no un objeto 'PostComment' ¿no? Lo estoy probando ahora para verificar. – Chev