Frage

Ich verwende MVC 3 in meinem Projekt, und ich bin ein sehr seltsames Verhalten zu sehen.

Ich versuche, ein verstecktes Feld für einen bestimmten Wert auf meinem Modell zu schaffen, das Problem ist, dass die eingestellte Wert auf dem Feld aus irgendeinem Grunde entspricht nicht den Wert im Modell.

z.

Ich habe diesen Code, nur als Test:

<%:Html.Hidden("Step2", Model.Step) %>
<%:Html.HiddenFor(m => m.Step) %>

Ich würde denken, dass beide versteckte Felder würden den gleichen Wert haben. Was ich tue, ist, setzen Sie den Wert auf 1 das erste Mal, dass ich die Ansicht anzuzeigen, und dann nach der Vorlage ich den Wert des Modellfeldes erhöhen 1.

Also, das erste Mal, dass ich die Seite mache beiden Regler den Wert 1 haben, aber beim zweiten Mal der Werte wiedergegeben ist diese:

<input id="Step2" name="Step2" type="hidden" value="2" />
<input id="Step" name="Step" type="hidden" value="1" />

Wie Sie sehen können, ist der erste Wert ist richtig, aber der zweite Wert scheint das gleiche wie das erste Mal, dass ich die Ansicht angezeigt werden.

Was bin ich? Sind die * für Html Helfer Cachen die Werte in irgendeiner Weise? Wenn ja, wie kann ich deaktivieren Sie diese Caching?.

Danke für Ihre Hilfe.

War es hilfreich?

Lösung

Das ist normal und es ist wie HTML Helfer arbeiten. Sie verwenden zuerst den Wert der POST-Anforderung und danach den Wert im Modell. Dies bedeutet, dass selbst wenn Sie den Wert des Modells in Ihrer Controller-Aktion ändern, wenn die gleiche Variable in der POST-Anforderung ist Ihre Änderung wird ignoriert und der Wertansatz verwendet werden.

Eine mögliche Abhilfe ist es, diesen Wert aus dem Modellzustand in der Controller-Aktion zu entfernen, die den Wert zu ändern versucht:

// remove the Step variable from the model state 
// if you want the changes in the model to be
// taken into account
ModelState.Remove("Step");
model.Step = 2;

Eine andere Möglichkeit ist es, eine Gewohnheit zu schreiben HTML-Helfer, die immer den Wert des Modells verwenden und POST-Werte ignorieren.

Und noch eine andere Möglichkeit:

<input type="hidden" name="Step" value="<%: Model.Step %>" />

Andere Tipps

stieß ich auf das gleiche Problem, wenn ein Assistent für das Schreiben, das zeigt verschiedene Teile eines größeren Modells bei jedem Schritt.
Daten und / oder Fehler aus „Schritt 1“ verwechselt werden sollten mit „Step 2“, usw., bis ich schließlich erkennen, dass Model zu ‚Schuld‘ war.

Dies war meine einfache Lösung:

if (oldPageIndex != newPageIndex)
{
    ModelState.Clear(); // <-- solution
}

return View(model[newPageIndex]);

Dieser Code wird nicht funktionieren

// remove the Step variable from the model state
// if you want the changes in the model to be
// taken into account
ModelState.Remove("Step");
model.Step = 2;

... weil HiddenFor immer (!) Liest aus Model nicht das Modell selbst. Und wenn es nicht die „Step“ Schlüssel nicht finden wird es den Standardwert für diese Variable Typ herzustellen, die in diesem Fall 0 sein wird,

Hier ist die Lösung. Ich schrieb es für mich aber nicht dagegen, es zu teilen, weil ich viele Leute sehen, mit diesem frechen HiddenFor Helfer zu kämpfen haben.

public static class CustomExtensions
{
    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression);
    }

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression, htmlAttributes);
    }

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
    {
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression, htmlAttributes);
    }

    private static void ReplacePropertyState<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        string text = ExpressionHelper.GetExpressionText(expression);
        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(text);
        ModelStateDictionary modelState = htmlHelper.ViewContext.ViewData.ModelState;
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

        if (modelState.ContainsKey(fullName))
        {                
            ValueProviderResult currentValue = modelState[fullName].Value;
            modelState[fullName].Value = new ValueProviderResult(metadata.Model, Convert.ToString(metadata.Model), currentValue.Culture);
        }
        else
        {
            modelState[fullName] = new ModelState
            {
                Value = new ValueProviderResult(metadata.Model, Convert.ToString(metadata.Model), CultureInfo.CurrentUICulture)
            };
        }
    }
}

Dann einfach Sie es wie gewohnt von innen Sie sehen:

@Html.HiddenFor2(m => m.Id)

Es lohnt sich zu erwähnen, es mit einer Sammlung funktioniert auch.

Ich kämpfe auch mit der gleichen Situation wie ich glaube, wo ich das gleiche Modell Zustand zwischen den Anrufen zu verwenden, und wenn ich ein Modell Eigenschaft auf Backend ändern. Obwohl, es spielt keine Rolle für mich, wenn ich textboxfor oder hiddenfor verwenden.

Ich habe gerade Bypass die Situation von Seite Skripte mit dem Modellwert als js Variablen zu speichern, weil ich die Hidden zu diesem Zweck am Anfang brauchen.

Nicht sicher, ob das hilft, aber nur betrachten ..

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top