ASP.NET MVC 및 뷰 상태
지금은 이런 질문을 좀 보았지만, 정확히 묻고 싶은 것이 아니기 때문에, 소리지르는 모든 분들께는 사과드립니다 :).
ASP를 거의 못 만졌어요.NET MVC 하지만 ViewState/ControlState는 없는 것으로 알고 있습니다...좋아요 그럼 제 질문은 통제 상태를 유지하는 대안이 무엇인가요?ASP를 시뮬레이션할 수 있는 오래된 학교 ASP로 돌아갑니다.NET ViewState/ControlState는 컨트롤의 상태 또는 MVC를 사용하여 숨겨진 폼 입력을 생성함으로써 항상 AJAX를 가정하고 모든 상태 클라이언트 측을 유지하며 업데이트하기 위해 AJAX 호출을 수행합니까?
이 질문에는 Asp.net mvc?에서 보기 상태 유지라는 몇 가지 답변이 있지만, 답변에서 찾고 있는 내용은 정확하지 않습니다.
업데이트: 지금까지 답변해주신 모든 분들께 감사드립니다.내가 찾고 있지 않은 것과 내가 찾고 있는 것을 분명히 하기 위해서입니다.
찾고 있지 않음:
- 세션 솔루션
- 쿠키용액
- MVC에서 WebForms를 모방하지 않음
제가 찾고 있는 것:
- 데이터가 컨트롤로 리바운드되지 않은 경우에만 포스트백 상태를 유지하는 방법입니다.초기 페이지 로드에 그리드만 바인딩하는 시나리오, 즉 필요할 때 데이터만 바인딩하는 시나리오로 WebForms를 생각해 보십시오.말씀드린 것처럼, 저는 웹폼을 흉내 내려고 하는 것이 아니라, MVC가 제공하는 메커니즘이 무엇인지 궁금할 뿐입니다.
컨벤션은 너무 많은 후프를 거치지 않고 이미 이용할 수 있습니다.이 방법은 보기에 전달하는 모델을 기준으로 텍스트 상자 값을 연결하는 것입니다.
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult CreatePost()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreatePost(FormCollection formCollection)
{
try
{
// do your logic here
// maybe u want to stop and return the form
return View(formCollection);
}
catch
{
// this will pass the collection back to the ViewEngine
return View(formCollection);
}
}
다음 단계는 ViewEngine이 Collection 형식을 취하고 HTML 도움말을 사용하여 컬렉션 내의 키를 보기에 있는 ID 이름/값과 일치시킵니다.예를 들어,
<div id="content">
<% using (Html.BeginForm()) { %>
Enter the Post Title: <%= Html.TextBox("Title", Model["Title"], 50) %><br />
Enter the Post Body: <%= Html.TextArea("Body", Model["Body"]) %><br />
<%= Html.SubmitButton() %>
<% } %>
</div>
텍스트 상자와 텍스트 영역에 제목과 본문 ID가 있다는 것을 주목하십시오.이제 View's Model 개체에서 값을 어떻게 설정하는지 확인해 보십시오.양식 모음을 전달했으므로(양식 모음을 사용하여 보기를 강하게 입력하도록 설정해야 함) 이제 보기에 접근할 수 있습니다.또는 강력하게 입력하지 않고 ViewData["제목"] (제 생각엔.
마법의 뷰 상태를 푸프합니다.이 개념을 convention over configuration이라고 합니다.
이제 위 코드는 FormCollection을 사용하여 가장 단순하고 원시적인 형태입니다.폼 컬렉션 대신 보기 모델을 사용하기 시작하면 상황이 흥미로워집니다.모델/뷰 모델에 대한 자신의 유효성 검사를 추가하기 시작하고 컨트롤러가 사용자 지정 유효성 검사 오류를 자동으로 버블링하도록 할 수 있습니다.그래도 그건 다른 날에 대한 답입니다.
Post 개체 대신 Post FormView Model을 사용하는 것이 좋습니다.어느 쪽이든 작업 메서드에 개체를 요구하면 IsValid() 메서드를 호출할 수 있습니다.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreatePost(Post post)
{
// errors should already be in the collection here
if (false == ModelState.IsValid())
return View(post);
try
{
// do your logic here
// maybe u want to stop and return the form
return View(post);
}
catch
{
// this will pass the collection back to the ViewEngine
return View(post);
}
}
그리고 강력한 유형의 보기를 조정해야 합니다.
<div id="content">
<% using (Html.BeginForm()) { %>
Enter the Post Title: <%= Html.TextBox("Title", Model.Title, 50) %><br />
Enter the Post Body: <%= Html.TextArea("Body", Model.Body) %><br />
<%= Html.SubmitButton() %>
<% } %>
</div>
여기서 한 단계 더 나아가 컨트롤러에서 설정한 ModelState에서 직접 보기에 오류도 표시할 수 있습니다.
<div id="content">
<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) { %>
Enter the Post Title:
<%= Html.TextBox("Title", Model.Title, 50) %>
<%= Html.ValidationMessage("Title") %><br />
Enter the Post Body:
<%= Html.TextArea("Body", Model.Body) %>
<%= Html.ValidationMessage("Body") %><br />
<%= Html.SubmitButton() %>
<% } %>
</div>
이 접근 방식에서 흥미로운 점은 제가 유효성 검사 요약이나 보기의 개별 유효성 검사 메시지를 설정하지 않고 있다는 것입니다.저는 DDD 개념을 연습하는 것을 좋아하는데, 이것은 제 검증 메시지(및 요약)가 제 도메인에서 제어되고 모음 형태로 전달된다는 것을 의미합니다.그런 다음 (오류가 있는 경우) 컬렉션을 루프로 이동하여 현재 Model State에 추가합니다.오류 컬렉션을 추가합니다.나머지는 View(포스트)를 반환하면 자동으로 처리됩니다.
많은 컨벤션이 나왔습니다.이러한 패턴을 보다 자세히 다룰 수 있는 몇 권의 책은 다음과 같습니다.
그리고 첫 번째 순서로 전체 MVC 프레임워크의 원시 너트와 볼트를 다룹니다.후자는 Microsoft 공식 도구 이외의 고급 기술을 포함하고 있으며, 사용자의 삶을 훨씬 더 쉽게 만들 수 있는 몇 가지 외부 도구(캐슬 윈저, Moq 등)를 포함하고 있습니다.
보기는 MVC 패턴에서 무식해야 하며 컨트롤러가 제공하는 것만 표시합니다.(분명히 우리는 종종 논리적으로 끝나지만 전제는 그렇지 않습니다.) 결과적으로 컨트롤은 자신의 상태를 책임지지 않으며 컨트롤러에서 매번 제공됩니다.
저는 스티븐 샌더슨의 책 프로 ASP를 추천할 수 없습니다.A 프레스의 NET MVC는 이러한 패턴과 그 구현을 파악하기에 충분합니다.
웹 양식에서 컨트롤 값은 보기 상태로 유지되므로 이론적으로 각 포스트백으로 다시 초기화할 필요가 없습니다.값은 (이론적으로) 프레임워크에 의해 유지됩니다.
ASP.NET MVC에서는 패러다임을 따르는 경우 폼 요소에 대한 상태를 유지할 필요가 없습니다.양식 요소 값은 컨트롤러가 작업할 수 있는 게시물(유효성 검사, 데이터베이스 업데이트 등)에서 사용할 수 있습니다.게시물이 처리되면 표시되는 양식 요소의 경우 사용자(개발자)가 초기화할 책임이 있습니다. 프레임워크에서 자동으로 초기화되지는 않습니다.
즉, TempData(템프데이터)라는 메커니즘을 통해 컨트롤러가 리디렉션 후 다른 컨트롤러로 데이터를 전달할 수 있다는 것을 읽었습니다.실제로는 세션 변수(또는 쿠키로 구성하는 경우)이지만 다음 요청 후 자동으로 정리됩니다.
답은 상태를 유지하려는 제어 유형에 따라 달라집니다.기본적인 HTML 컨트롤의 경우 모델을 사용하여 상태를 유지하는 것이 매우 쉽습니다. 이렇게 하려면 강력하게 입력된 보기를 만들어야 합니다.
속성을 가진 사용자 모델이 있다면 다음과 같습니다.사용자 이름, 전체 이름, 전자 메일 보기에서 다음 작업을 수행할 수 있습니다.
<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) { %>
<fieldset>
<legend>User details</legend>
<%= Html.AntiForgeryToken() %>
<p>
<label for="Username">Username:</label>
<%= Html.Textbox("Username", Model.Username, "*") %>
</p>
<p>
<label for="FullName">FullName:</label>
<%= Html.Textbox("FullName", Model.FullName, "*") %>
</p>
<p>
<label for="Email">Email:</label>
<%= Html.Textbox("Email", Model.Email, "*") %>
</p>
<p>
<input type+"submit" value="Save user" />
</p>
</fieldset>
<% } %>
그러면 이 보기를 표시하는 컨트롤러 작업이 두 가지가 됩니다. 하나는 잊어버리고 다른 하나는 게시물에 표시됩니다.
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult User()
{
return View(new User())
}
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult User([Bind(Include = "Username,FullName,Email")]User user)
{
if (!ModelState.IsValid()) return View(user);
try
{
user.save()
// return the view again or redirect the user to another page
}
catch(Exception e)
{
ViewData["Message"] = e.Message;
return View(user)
}
}
이것이 당신이 찾고 있던 것이에요?아니면 요청 사이에 형식으로 표시되지 않는 모델의 상태를 유지하시겠습니까?
기억해야 할 중요한 점은 코드가 요청 기간 동안 서버에서 실행되어 종료된다는 것입니다. 요청 사이에 전달할 수 있는 유일한 정보는 기본 html 양식 데이터, url 매개 변수 및 세션 정보입니다.
다른 분들이 말씀하신 것처럼 스티브 샌더스의 프로 ASP를 적극 추천합니다.MVC Framework와 함께 작업하는 것에 대한 완전한 이해를 위한 NET MVC Framework.
숨겨진 필드:
<% using (Html.BeginForm<SomeController>(c=>c.SomeAction(null))) {%> <%= Html.Hidden("SomeField", Model.SomeField)%> <%= Html.Hidden("AnotherField", Model.AnotherField)%>
특정 모델 설정 및 명시적 필드 없음(숨김 필드 gives u).아래 예에서 모델은 컨트롤러가 마지막 게시물에서 받은 값으로 채워지므로 상태에 따라 필터링할 수 있는 페이지의 nojs 옵션을 사용할 수 있습니다.
Some Filter: <% using( Html.BeginForm<SomeController>( c => c.SomeAction(model.SomeField, model.AnotherField, model.YetAnotherField, null, model.SomeOtherField) )) { %> <%= Html.DropDownList("status", Model.StatusSelectList)%> <input type="submit" value="Filter" class="button" /> <% } %>
- 제출된 양식에 실패한 유효성 검사 메시지를 표시할 때 필드를 게시된 값으로 채우려면 확장 메서드를 사용하여 필드를 만듭니다.
- asp.net mvc 2에서 그들은 숨겨진 필드에 인스턴스를 저장하는 방법을 소개했습니다...부호화 + (내 생각에는) 부호화된
- TempData 위의 모든 것이 실행되지 않는 경우 (다음 요청 시 세션을 거칩니다 - 클리닝됨)
- 언급하신 것처럼, ajax를 사용할 때 상태는 이미 클라이언트 사이트의 이전 로드된 필드에 있습니다.만약 u8ron이 전체 게시물을 해야 한다면 js로 필요한 필드를 업데이트하세요.
위의 내용은 모두 다른 시나리오에서 사용할 수 있는 독립적인 옵션입니다.쿠키, 세션, DB에 저장된 것(다시 시작 가능한 다단계 마법사의 경우), 매개 변수가 작업에 전달되는 등 제가 언급하지 않은 더 많은 옵션들이 있습니다.그들 모두를 통제할 수 있는 하나의 메커니즘은 없으며, 있어서도 안 됩니다.
가장 좋은 방법은 원래 모델을 숨겨진 필드에 직렬화한 다음 역직렬화하여 게시물에 모델을 업데이트하는 것입니다.이는 뷰 상태 접근 방식과 다소 유사하며, 사용자가 직접 구현하기만 하면 됩니다.나는 이것을(를)
우선 일을 더 쉽게 할 수 있는 몇 가지 방법이 필요합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using LuvDaSun.Extensions;
using System.Web.UI;
namespace LuvDaSun.Web.Mvc
{
public static class HtmlHelperExtensions
{
static LosFormatter _losFormatter = new LosFormatter();
public static string Serialize(this HtmlHelper helper, object objectInstance)
{
var sb = new StringBuilder();
using (var writer = new System.IO.StringWriter(sb))
{
_losFormatter.Serialize(writer, objectInstance);
}
return sb.ToString();
}
}
[AttributeUsage(AttributeTargets.Parameter)]
public class DeserializeAttribute : CustomModelBinderAttribute
{
public override IModelBinder GetBinder()
{
return new DeserializeModelBinder();
}
}
public class DeserializeModelBinder : IModelBinder
{
static LosFormatter _losFormatter = new LosFormatter();
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.IsArray)
{
var type = bindingContext.ModelType.GetElementType();
var serializedObjects = (string[])bindingContext.ValueProvider.GetValue(bindingContext.ModelName).ConvertTo(typeof(string[]));
var deserializedObjects = Array.CreateInstance(bindingContext.ModelType.GetElementType(), serializedObjects.Length);
for (var index = 0; index < serializedObjects.Length; index++)
{
var serializedObject = serializedObjects[index];
var deserializedObject = _losFormatter.Deserialize(serializedObject);
deserializedObjects.SetValue(deserializedObject, index);
}
return deserializedObjects;
}
else
{
var serializedObject = (string)bindingContext.ValueProvider.GetValue(bindingContext.ModelName).ConvertTo(typeof(string));
var deserializedObject = _losFormatter.Deserialize(serializedObject);
return deserializedObject;
}
}
}
}
그럼 내 컨트롤러에 이런 것이 있습니다(제품을 업데이트하기 위해).
public ActionResult Update(string productKey)
{
var model = _shopping.RetrieveProduct(productKey);
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update([Deserialize]Shopping.IProduct _model, FormCollection collection)
{
UpdateModel(model);
model.Save();
return RedirectAfterPost();
}
직렬화된 객체를 다음과 같은 형태로 보관하는 숨겨진 필드가 필요합니다.
<%
using (Html.BeginRouteForm("Product", FormMethod.Post, new { id = UniqueID, }))
{
%>
<%= Html.Hidden("Model", Html.Serialize(Model)) %>
<h1>
Product bewerken</h1>
<p>
<label for="<%=UniqueID %>_Name">
Naam:</label>
<input id="<%=UniqueID %>_Name" name="Name" type="text" value="<%= Html.AttributeEncode(Model.Name) %>"
class="required" />
<br />
</p>
<p>
Omschrijving:<br />
<textarea id="<%= UniqueID %>_Description" name="Description" cols="40" rows="8"><%= Html.Encode(Model.Description) %></textarea>
<br />
</p>
<p>
<label for="<%=UniqueID %>_Price">
Prijs:</label>
<input id="<%= UniqueID %>_Price" name="Price" type="text" value="<%= Model.Price.ToString("0.00") %>"
class="required" />
<br />
</p>
<ul class="Commands">
<li><a href="" class="ClosePopup">Annuleren</a></li>
<li>
<input type="submit" value="Opslaan" /></li>
</ul>
<%
}
%>
<script type="text/javascript">
jQuery('#<%= UniqueID %>').validate();
</script>
보시다시피 숨겨진 필드(Model)가 양식에 추가됩니다.여기에는 원래 개체에 대한 직렬화 정보가 들어 있습니다.양식이 게시되면 숨김 필드도 함께 게시되고(물론) 컨텐츠는 사용자 지정 모델 바인더를 통해 원래 개체에 대해 역직렬화된 다음 컨트롤러에 의해 업데이트되고 저장됩니다.
직렬화하려는 개체는 Serializable 속성으로 장식하거나 개체를 문자열로 변환할 수 있는 TypeConverter가 있어야 합니다.
LosFormatter(Limited Object Serialization)는 웹 양식의 뷰 상태에서 사용됩니다.또한 직렬화 데이터의 암호화 n을 제공합니다.
인사말...
아약스의 전화가 우리가 하는 일입니다.일반적으로 그리드에 대해 말씀하시는 경우 JQGrid와 AJAX 구현을 권장하는 방법을 확인해 보십시오.
언급URL : https://stackoverflow.com/questions/1473483/asp-net-mvc-and-viewstate
'it-source' 카테고리의 다른 글
두 날짜 사이의 시간 차이(시간 단위)를 구하는 방법 (0) | 2023.10.23 |
---|---|
AJAX 호출 데이터를 반환하는 자바스크립트 함수 (0) | 2023.10.23 |
플로트 분할을 할 때 이중으로 주조하고 뒤로 주조할 때 정확도가 향상됩니까? (0) | 2023.10.23 |
안드로이드 버전과 코드 버전 번호를 변경하는 방법은? (0) | 2023.10.23 |
파이썬 셸에서 pyspark 가져오기 (0) | 2023.10.23 |