2009-08-24 16 views
5

Mi vista utiliza ModelX para representar mi formulario HTML y mi acción de controlador toma ModelY como entrada al guardar el formulario. Parece que la API tipo de letra segura asume que estoy usando el mismo modelo en ambos lugares.ASP.NET MVC - Typesafe Html.TextBoxFor con diferente modelo de salida

¿Es posible usar diferentes modelos y ser seguro sin crear mis propios ayudantes?

<% = Html.TextBoxFor(x => x.Text) %>

me gustaría algo como esto. Existe ?

<% = Html.TextBoxFor<InputModel,OutputModel>(input=>input.Text, output=>output.SomeOtherText) 

Respuesta

1

¿Es posible utilizar diferentes modelos y beeing un tipo seguro sin crear mis propios ayudantes?

Solo mediante el uso de la herencia. Entonces tendrás un modelo base con todas las propiedades.

Considere XForms.
Pero realmente no entiendo el propósito de InputModel y OutputModel en la muestra.

+0

¿Qué tal algunos ejemplos en XForms que se aplica a su caso. –

+0

¿Puedes dar una muestra ** real ** de lo que quieres hacer? Realmente no entiendo lo que estás tratando de lograr (modelo de entrada y salida?). –

+1

Dmitriy Nagirnyak: La idea es que use un modelo para poblar la vista. Es posible que no use el mismo modelo para guardar datos de la vista. Son para diferentes preocupaciones. – BjartN

13

He encontrado una solución que implica crear un nuevo helper html. El OP es correcto al decir que a veces es inapropiado usar la misma clase como parámetro para el método de acción y para la página de visualización. A veces queremos pasar MÁS información a la página de visualización que lo que el usuario nos devuelve en la publicación del formulario.

La solución me ocurrió es utilizar un método de extensión HtmlHelper, que llamé HtmlHelperFor (T obj) que utilizo como a continuación:

<% var productForm = Html.HtmlHelperFor(Model.Product); %> 

y luego lo uso como a continuación:

<%= productForm.TextBoxFor(x => x.Name) %> 

el método de extensión es a continuación:

public static HtmlHelper<T> HtmlHelperFor<T>(this HtmlHelper html, T model) 
{ 
    var newViewData = new ViewDataDictionary(html.ViewDataContainer.ViewData) { Model = model }; 
    ViewContext newViewContext = new ViewContext(html.ViewContext.Controller.ControllerContext, html.ViewContext.View, newViewData, html.ViewContext.TempData, html.ViewContext.Writer); 
    var viewDataContainer = new ViewDataContainer(newViewContext.ViewData); 
    return new HtmlHelper<T>(newViewContext, viewDataContainer, html.RouteCollection); 
} 

el ViewDataContainer es una implementación de la IVi ewDataContainer interfaz que se encuentra en Sysetm.Web.Mvc:

public class ViewDataContainer : System.Web.Mvc.IViewDataContainer 
{ 
    public ViewDataContainer(System.Web.Mvc.ViewDataDictionary viewData) 
    { 
     ViewData = viewData; 
    } 

    public System.Web.Mvc.ViewDataDictionary ViewData { get; set; } 
} 

las llamadas anteriores le permitirá tener un objeto Product como parte de los parámetros del método que acepta el cargo, en lugar de una clase que contiene proyecto que se normalmente pasaría a su vista.

+1

¡Gracias por mostrar tu solución! Estoy pensando en ampliar la idea creando algo así como un 'ScopedMvcForm', y un ayudante correspondiente' BeginScopedForm'.Me gustaría poder escribir: 'using (var form = BeginScopedForm (Model.Product)) {form.TextBoxFor (...)} – Ragge

+1

Me gustaría revocar esto un montón de veces si pudiera. No solo responde una pregunta directa que tuve (cómo hacer la misma operación que describe la pregunta, sino para las llamadas a 'DisplayNameFor'), sino que también proporciona una buena ventana sobre cómo se crea un HtmlHelper y cómo crear uno dado una vista existente . – daveaglick

+0

@TahirHassan ¿cómo podemos hacer lo mismo con ASP.NET Core? – tchelidze

Cuestiones relacionadas