2009-10-14 9 views
5

ASP.NET MVC 응용 프로그램에서 Redirect After Post 패턴을 사용하고 있습니다.ASP.NET MVC에서 리디렉션 후

  1. 사용자가 자신이 양식을 작성하도록 요청된다 /controller/index로 이동 : 나는 다음과 같은 시나리오가 있습니다.
  2. 양식 값은 /controller/calculate으로 게시됩니다.
  3. Calculate 액션은 입력을 기반으로 계산을 수행하고 작업 결과를 포함하는 복잡한 객체를 인스턴스화합니다. 이 개체는 TempData에 저장되고 사용자는 /controller/result으로 리디렉션됩니다.
  4. /controller/resultTempData에서 결과를 검색하여 사용자에게 렌더링합니다.

이 방법의 문제점은 /controller/result에 결과를 보면서 사용자가 F5 안타 더 TempData로 렌더링 할 수없는 페이지가 만료되었고 결과 개체가 더 이상 사용할 수 있다는 것이다.

이 동작은 사용자가 원하지 않습니다. 한 가지 가능한 해결책은 POST 후에 리디렉션하는 대신 결과보기를 렌더링하는 것입니다. 이제 사용자가 F5를 누르면 폼을 다시 게시할지 묻는 브라우저 대화 상자가 나타납니다. 이것은 또한 바람직하지 않았습니다.

내가 생각했던 가능한 해결책은 결과 개체를 직렬화하고 리디렉션하기 전에 URL에 전달하는 것이 었습니다. 그러나 AFAIK에는 GET 요청의 길이에 몇 가지 제한이 있으며 개체가 꽤 커지면이 제한에 부딪 힐 수 있습니다 (특히 base64로 인코딩 된 경우).

또 다른 가능성은 TempData 대신 Session 개체를 사용하여 결과를 유지하는 것입니다. 그러나이 솔루션을 구현하기 전에 더 나은 방법이 있는지 알고 싶습니다.


UPDATE :

또한 나는 경우가 실제로 작동하는 /controller/result 액션 내부 TempData에 결과 개체를 다시 넣어 발견 문제 조사 :

public ActionResult Result() 
{ 
    var result = TempData["result"]; 
    TempData["result"] = result; 
    return View(result); 
} 

그러나이 종류의 느낌을 더러운. 이 접근법에 부작용이있을 수 있습니까 (예 : 현재 InProc을 사용하는 out-of-process 세션 공급자로 전환)?

+0

"리디렉션"이라고 말하면 RedirectToAction을 (를) 호출하고 있습니까? – Will

+0

예, RedirectToAction. –

답변

5

고유 한 키를 사용하여 세션에 저장하고 키를 URL의 일부로 전달하십시오. 그런 다음 세션이 살아있는 한 뒤로/앞으로 버튼을 사용하여 마음의 콘텐츠를 볼 수 있으며 URL이 제대로 응답하게 할 수 있습니다.또는 ASP 캐시를 사용할 수도 있지만 일반적으로 사용자간에 공유되는 개체에 대해서는이를 예약합니다. 물론 계산에 사용 된 매개 변수를 키로 사용하여 캐시에서 결과를 찾으면 간단히 다시 사용할 수 있습니다.

+0

감사합니다. 좋은 제안입니다. URL에 전달 된 고유 한 키로 구현하려고합니다. –

1

TempData는 일반적으로 작업 엔터티를 저장하지 않고 메시지를 사용자에게 전달하는 데 유용합니다 (사용자 새로 고침은 TempData의 내용을 암호화하지 않습니다).

나는 이런 종류의 정보를 저장하는 세션보다 더 적절한 장소를 모른다. 나는 일반적인 생각이 세션을 가능한 한 작게 유지한다고 생각한다. 개인적으로 나는 보통 특정 객체를 세션에 추가하거나 제거하기 위해 래퍼를 작성한다. 가능한 경우 수동으로 청소하십시오.

다른 방법으로는 오래된 항목을 정기적으로 제거하는 데이터베이스에 저장할 수 있습니다.

2

결과 URL이 의미가있을 때 게시 이후 리디렉션이 훨씬 더 의미가 있다고 생각합니다. 귀하의 경우 계산에 필요한 모든 데이터가/controller/result의 URL에 있음을 의미합니다.

/controller/calculate는 계산을 수행하지 않고/controller/result를 계산합니다.

계산을 완료하는 데 도움이되는 경우 : 계산에 필요한 값을 해시하고 캐시의 키로 사용합니다. 사용자가 새로 고치면 그는 캐시에 도달합니다.

의미있는 URL이 없으면/controller/index에 게시 할 수 있습니다. 사용자가 F5 키를 누르면 계산이 다시 시작되지만 해시를 키로 사용하는 캐시가 다시 도움이됩니다.

+0

계산하기 전에 입력을 확인하고 오류가있는 경우 미리 채워진 값과 오류 필드가 같은 양식을 빨간색으로 표시해야합니다. Result 액션에서 계산이 완료되면 ModelState 오류를 어떻게 처리 할 수 ​​있습니까? 다시 인덱스 작업으로 리디렉션하고 모든 입력 값과 유효성 검사 오류를 TempData에 입력하여 양식을 올바르게 표시 할 수 있습니까? –

+0

결과에서 검증이 어려워집니다. 유효성이 검사 된 값으로 리디렉션합니다. 가장 쉬운 방법은 데이터를 색인하고 유효성을 검사하기 위해 게시하고 오류를 표시하는 것입니다. –

0

모든 POST를 확인하기 위해 일회성 키를 사용하여 온라인 뱅킹 사이트의 많은 은행에 비슷한 아이디어를 적용 할 수 있습니다. 양식을위한 HTML 도우미와 검증을 위해 서비스 계층 (예 :)에 통합 할 수 있습니다.

양식의 인스턴스를 한 번만 게시하고 싶다고 가정 해 보겠습니다. 폼에 guid를 추가하십시오. 양식이 다시 게시되지 않고 데이터가 커밋 된 경우 GUID를 무효화하고 GET 작업으로 리디렉션하려고합니다. 양식이 유효하지 않다고 말하면 페이지가 다시 게시되면 다음 게시물 시도를 기다리는 양식에 새 (유효한) GUID가 필요합니다.

GUID가 필요에 따라 생성되고 DB의 테이블에 추가됩니다. 그들은 (POSTS에 의해 성공했는지 여부에 관계없이) 무효화되었으므로 표에 표시됩니다. 앱이 얼마나 무겁고 한번에 얼마나 많이 렌더링되었지만 아직 게시되지 않은 양식인지에 따라 표를 100 줄 또는 1000 줄로 자르고 싶을 수도 있습니다.

나는이 디자인을 실제로 미세 조정하지는 않았지만 효과가있을 것이라고 생각합니다. TempData만큼 냄새가 없으며 여전히 PRG 패턴을 고수 할 수 있습니다.

PRG를 사용하면 일종의 임시 변수에서 새 데이터를 GET 작업으로 보내지 않습니다. 데이터 저장소에서 다시 커밋 할 위치를 쿼리하려고합니다.

+0

현재 응용 프로그램에 데이터 저장소가 없습니다. 메모리 내 모든 작업을 수행합니다 (계산 만하고 지속성 없음). 그래서 TempData 또는 Session을 임시 데이터 저장소로 사용하는 것이 좋습니다. –

0

Michael이 말했듯이 TempData에는 단일 목적 만 있습니다. - 한 번의 여행과 한 번의 여행을위한 개체를 저장합니다. 내가 이해할 수 있듯이, TempData는 본질적으로 당신이 사용할 수있는 것과 동일한 Session 객체를 사용하지만, 다음 여행에서 세션에서 객체를 자동으로 제거합니다.

TempData로 다시 푸시하기보다는 Session imho로 고정하십시오.

관련 문제