Asp.net MVC ModelState.Clear ModelState.Clear()했지만 왜 / 어떻게 작동했는지

누구든지 Asp.net MVC에서 ModelState의 역할 (또는 링크)에 대한 간결한 정의를 줄 수 있습니까? 특히 어떤 상황에서 전화가 필요하거나 바람직한 지 알아야합니다 ModelState.Clear().

비트 오픈 엔드 허 … 미안합니다. 제가 간절히하고있는 일을 말해 주면 도움이 될 것 같습니다.

“페이지”라는 컨트롤러에 대한 편집 작업이 있습니다. 페이지의 세부 정보를 변경하는 양식을 처음 보았을 때 모든 것이 잘로드됩니다 ( “MyCmsPage”개체에 바인딩). 그런 다음 MyCmsPage 개체의 필드 ( MyCmsPage.SeoTitle) 중 하나에 대한 값을 생성하는 단추를 클릭합니다 . 그것은 잘 생성되고 객체를 업데이트 한 다음 새로 수정 된 페이지 객체로 작업 결과를 반환하고 관련 텍스트 상자 (를 사용하여 렌더링 <%= Html.TextBox("seoTitle", page.SeoTitle)%>됨)가 업데이트 될 것으로 기대 하지만 아쉽게도로드 된 이전 모델의 값을 표시합니다.

나는 그것을 사용하여 해결 ModelState.Clear()했지만 왜 / 어떻게 작동했는지 알 필요가 있으므로 맹목적으로하는 것이 아닙니다.

PageController :

[AcceptVerbs("POST")]
public ActionResult Edit(MyCmsPage page, string submitButton)
{
    // add the seoTitle to the current page object
    page.GenerateSeoTitle();

    // why must I do this?
    ModelState.Clear();

    // return the modified page object
     return View(page);
 }

Aspx :

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyCmsPage>" %>
....
        <div class="c">
            <label for="seoTitle">
                Seo Title</label>
            <%= Html.TextBox("seoTitle", page.SeoTitle)%>
            <input type="submit" value="Generate Seo Title" name="submitButton" />
        </div>


답변

MVC의 버그라고 생각합니다. 나는 오늘 몇 시간 동안이 문제로 고생했습니다.

이것을 감안할 때 :

public ViewResult SomeAction(SomeModel model)
{
    model.SomeString = "some value";
    return View(model);
}

뷰는 변경 사항을 무시하고 원본 모델로 렌더링됩니다. 그래서 나는 같은 모델을 사용하는 것을 좋아하지 않을 수 있다고 생각했기 때문에 다음과 같이 시도했습니다.

public ViewResult SomeAction(SomeModel model)
{
    var newModel = new SomeModel { SomeString = "some value" };
    return View(newModel);
}

그리고 여전히 뷰는 원래 모델로 렌더링됩니다. 이상한 점은 뷰에 중단 점을 놓고 모델을 살펴보면 변경된 값이 있다는 것입니다. 그러나 응답 스트림에는 이전 값이 있습니다.

결국 나는 당신이했던 것과 같은 일을 발견했습니다.

public ViewResult SomeAction(SomeModel model)
{
    var newModel = new SomeModel { SomeString = "some value" };
    ModelState.Clear();
    return View(newModel);
}

예상대로 작동합니다.

나는 이것이 “기능”이라고 생각하지 않습니까?


답변

최신 정보:

  • 이것은 버그가 아닙니다.
  • View()POST 작업에서 반환 을 중지하십시오 . 대신 PRG 를 사용 하고 작업이 성공하면 GET으로 리디렉션 하십시오 .
  • 당신이하면 된다 을 반환 View()후 조치에서 양식 유효성 검사를 수행하고 그에게 길을 어떻게 MVC가 설계 헬퍼 내장 사용합니다. 이렇게하면 사용할 필요가 없습니다..Clear()
  • 이 작업을 사용하여 SPA에 대한 ajax를 반환 하는 경우 웹 API 컨트롤러를 ModelState사용하고 어쨌든 사용해서는 안되므로 잊어 버립니다 .

이전 답변 :

MVC의 ModelState는 주로 해당 개체가 유효한지 여부와 관련하여 모델 개체의 상태를 설명하는 데 주로 사용됩니다. 이 튜토리얼 은 많은 것을 설명해야합니다.

일반적으로 ModelState는 MVC 엔진에서 유지 관리하므로 지울 필요가 없습니다. 수동으로 지우면 MVC 유효성 검사 모범 사례를 준수하려고 할 때 원하지 않는 결과가 발생할 수 있습니다.

제목의 기본값을 설정하려는 것 같습니다. 이것은 모델 객체가 인스턴스화 될 때 (어딘가에있는 도메인 레이어 또는 객체 자체-매개 변수없는 ctor) get 액션에서 처음으로 페이지로 내려가거나 클라이언트에서 완전히 내려갈 때 (ajax 또는 무언가를 통해) 수행되어야합니다. 사용자가 입력 한 것처럼 나타나고 게시 된 양식 컬렉션으로 돌아옵니다. 양식 컬렉션을받을 때이 값을 추가하는 방법 (POST 작업 // 편집에서)이이 기괴한 동작을 유발 하여 작동 하는 .Clear() 것처럼 보일 수 있습니다. 저를 믿으십시오-당신은 클리어를 사용하고 싶지 않습니다. 다른 아이디어 중 하나를 시도하십시오.


답변

개별 필드의 값을 지우려면 다음 기술이 유용하다는 것을 알았습니다.

ModelState.SetModelValue("Key", new ValueProviderResult(null, string.Empty, CultureInfo.InvariantCulture));

참고 :
“키”를 재설정하려는 필드의 이름으로 변경하십시오.


답변

ModelState는 기본적으로 유효성 검사 측면에서 모델의 현재 상태를 유지합니다.

ModelErrorCollection : 모델이 값을 바인딩하려고 할 때 오류를 나타냅니다. 전의.

TryUpdateModel();
UpdateModel();

또는 ActionResult의 매개 변수처럼

public ActionResult Create(Person person)

ValueProviderResult : 시도 된 모델 바인딩에 대한 세부 정보를 보유합니다. 전의. AttemptedValue, Culture, RawValue .

Clear () 메서드는 검사하지 않은 결과를 초래할 수 있으므로주의해서 사용해야합니다. 그리고 AttemptedValue와 같은 ModelState의 멋진 속성을 잃게 될 것입니다. 이것은 백그라운드에서 MVC가 오류 발생시 양식 값을 다시 채우는 데 사용됩니다.

ModelState["a"].Value.AttemptedValue

답변

의심스러운 양식의 모델을 업데이트하고 성능상의 이유로 ‘액션으로 리디렉션’을 원하지 않는 인스턴스가 있습니다. 숨겨진 필드의 이전 값이 업데이트 된 모델에 유지되어 모든 종류의 문제가 발생했습니다!.

몇 줄의 코드가 곧 제거하려는 ModelState 내의 요소를 식별 했으므로 (유효성 검사 후) 새 값이 다음 형식으로 사용되었습니다.

while (ModelState.FirstOrDefault(ms => ms.Key.ToString().StartsWith("SearchResult")).Value != null)
{
    ModelState.Remove(ModelState.FirstOrDefault(ms => ms.Key.ToString().StartsWith("SearchResult")));
}

답변

우리 중 많은 사람들이 이것에 물린 것처럼 보이며 이것이 발생하는 이유가 타당하지만 ModelState가 아닌 Model의 값이 표시되도록하는 방법이 필요했습니다.

일부는을 제안 ModelState.Remove(string key)했지만 key특히 중첩 모델의 경우 무엇 이어야 하는지 명확하지 않습니다 . 이를 지원하기 위해 내가 생각 해낸 몇 가지 방법이 있습니다.

RemoveStateFor메서드는 ModelStateDictionary원하는 속성에 대한, 모델 및 식을 사용하여 제거합니다. HiddenForModel먼저 ModelState 항목을 제거하여 모델의 값만 사용하여 숨겨진 입력 필드를 만드는 데 뷰에서 사용할 수 있습니다. (다른 도우미 확장 메서드의 경우 쉽게 확장 할 수 있습니다.)

/// <summary>
/// Returns a hidden input field for the specified property. The corresponding value will first be removed from
/// the ModelState to ensure that the current Model value is shown.
/// </summary>
public static MvcHtmlString HiddenForModel<TModel, TProperty>(this HtmlHelper<TModel> helper,
    Expression<Func<TModel, TProperty>> expression)
{
    RemoveStateFor(helper.ViewData.ModelState, helper.ViewData.Model, expression);
    return helper.HiddenFor(expression);
}

/// <summary>
/// Removes the ModelState entry corresponding to the specified property on the model. Call this when changing
/// Model values on the server after a postback, to prevent ModelState entries from taking precedence.
/// </summary>
public static void RemoveStateFor<TModel, TProperty>(this ModelStateDictionary modelState, TModel model,
    Expression<Func<TModel, TProperty>> expression)
{
    var key = ExpressionHelper.GetExpressionText(expression);

    modelState.Remove(key);
}

다음과 같은 컨트롤러에서 호출하십시오.

ModelState.RemoveStateFor(model, m => m.MySubProperty.MySubValue);

또는 다음과 같은보기에서 :

@Html.HiddenForModel(m => m.MySubProperty.MySubValue)

System.Web.Mvc.ExpressionHelperModelState 속성의 이름을 가져 오는 데 사용 합니다.


답변

유효성이 검증되지 않은 경우 값을 업데이트하거나 재설정하고 싶었고이 문제가 발생했습니다.

쉬운 대답 인 ModelState.Remove는 문제가 있습니다. 도우미를 사용하는 경우 이름을 실제로 알지 못하기 때문입니다 (이름 지정 규칙을 따르지 않는 한). 사용자 지정 도우미와 컨트롤러가 이름을 가져 오는 데 사용할 수 있는 함수를 만들지 않는 한 .

이 기능은 도우미의 옵션으로 구현 되었어야합니다. 기본적으로는 이 작업을 수행 하지 않지만 승인되지 않은 입력을 다시 표시하려면 그렇게 말할 수 있습니다.

그러나 적어도 나는 지금 문제를 이해합니다.).