[asp.net-mvc] 잘못된 값을 가진 ASP.Net MVC Html.HiddenFor

내 프로젝트에서 MVC 3을 사용하고 있으며 매우 이상한 동작을보고 있습니다.

내 모델의 특정 값에 대해 숨겨진 필드를 만들려고하는데 문제는 어떤 이유로 필드에 설정된 값이 모델의 값과 일치하지 않는다는 것입니다.

예 :

테스트와 마찬가지로이 코드가 있습니다.

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

숨겨진 필드 모두 동일한 값을 가질 것이라고 생각합니다. 내가하는 일은보기를 처음 표시 할 때 값을 1로 설정 한 다음 제출 후 모델 필드의 값을 1 씩 늘리는 것입니다.

따라서 페이지를 처음 렌더링 할 때 두 컨트롤의 값은 1이지만 두 번째 렌더링 값은 다음과 같습니다.

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

보시다시피 첫 번째 값은 정확하지만 두 번째 값은 처음보기를 표시 할 때와 같은 것 같습니다.

내가 무엇을 놓치고 있습니까? * For Html 헬퍼가 어떤 방식으로 값을 캐싱합니까? 그렇다면이 캐싱을 어떻게 비활성화 할 수 있습니까?

당신의 도움을 주셔서 감사합니다.



답변

그것은 정상이며 HTML 도우미가 작동하는 방식입니다. 먼저 POST 요청의 값을 사용하고 그 후에 모델의 값을 사용합니다. 이는 POST 요청에 동일한 변수가있는 경우 컨트롤러 조치에서 모델 값을 수정하더라도 수정이 무시되고 POST 값이 사용됨을 의미합니다.

가능한 해결 방법 중 하나는 값을 수정하려고하는 컨트롤러 조치의 모델 상태에서이 값을 제거하는 것입니다.

// 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;

또 다른 가능성은 항상 모델 값을 사용하고 POST 값을 무시하는 사용자 정의 HTML 헬퍼를 작성하는 것입니다.

그리고 또 다른 가능성 :

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


답변

모든 단계에서 더 큰 모델의 다른 부분을 보여주는 마법사를 작성할 때도 같은 문제가 발생했습니다.
ModelState가 ‘비난’되었다는 것을 마침내 깨달을 때까지 “단계 1″의 데이터 및 / 또는 오류가 “단계 2″등과 혼합됩니다.

이것은 나의 간단한 해결책이었습니다.

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

return View(model[newPageIndex]);


답변

이 코드는 작동하지 않습니다

// 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;

… 숨겨져 있기 때문에 항상 (!)는 모델 자체가 아닌 ModelState에서 읽습니다. “Step”키를 찾지 못하면 해당 변수 유형에 대한 기본값 인 0이됩니다.

해결책은 다음과 같습니다. 나는 그것을 위해 직접 작성했지만 그것을 공유하는 것을 신경 쓰지 않습니다. 많은 사람들 이이 장난 꾸러기 HiddenFor 도우미로 고심하고 있습니다.

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)
            };
        }
    }
}

그런 다음보기 내에서 평소와 같이 사용하십시오.

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

컬렉션에서도 작동한다는 것은 언급 할 가치가 있습니다.


답변

전화와 동일한 모델 상태를 사용하고 백엔드에서 모델 속성을 변경할 때와 같은 상황으로 어려움을 겪고 있습니다. textboxfor 또는 hiddenfor를 사용하면 나에게 중요하지 않습니다.

페이지 스크립트를 사용하여 모델 값을 js 변수로 저장하여 상황을 우회합니다. 처음에는 해당 필드에 숨겨진 필드가 필요하기 때문입니다.

이것이 도움이되는지 확실하지 않지만 고려하십시오 ..


답변