2009-03-23 38 views
57

Tôi muốn lấy dữ liệu được nhập trong biểu mẫu người dùng MVC và hiển thị dữ liệu ở chế độ xem khác.MVC - Truyền dữ liệu với RedirectToAction()

Lớp có biến tin sau:

IList<string> _pagecontent = new List<string>(); 

Hành động sau đây chấp nhận một đối tượng FormCollection, xác nhận nó, và chuyển nó vào "Preview" xem như một danh sách:

[Authorize(Roles = "Admins")] 
[ValidateInput(false)] 
[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult UpdateContent(FormCollection collection) 
{ 
    if (ModelState.IsValid) 
    { 
     string PageToInsert = collection["PageToInsert"]; 
     string PageHeader = collection["PageHeader"]; 
     string PageBody = collection["PageBody"]; 

     //validate, excluded... 

     _pagecontent.Add(PageToInsert); 
     _pagecontent.Add(PageHeader); 
     _pagecontent.Add(PageBody); 

    } 
    return RedirectToAction("Preview", _pagecontent); 
} 

Chế độ xem trước có Chỉ thị trang sau để chuyển đối tượng được nhập mạnh mẽ Danh sách:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Template.Master" Inherits="System.Web.Mvc.ViewPage<List<string>>" %> 

Tôi hy vọng sẽ có thể sử dụng đối tượng Model để lấy dữ liệu của tôi, nhưng tôi không thể. Tại dòng sau, tôi nhận được một ngoại lệ error index out of bounds, trong đó nêu các chỉ số phải không âm và nhỏ hơn kích thước của bộ sưu tập:

<% if (Model[0].ToString() == "0") { %> 

Và một số thông số lạ đã được thêm vào URL, vì nó giải quyết để http://localhost:1894/Admin/Preview?Capacity=4&Count=3

Vì vậy, tôi có hai câu hỏi:

  1. Khi tôi gọi RedirectToAction và vượt qua nó Danh sách của tôi, tại sao nó không thể tiếp cận trong đối tượng mẫu của xem?
  2. Cách thích hợp để thực hiện những gì tôi đang cố gắng làm, cụ thể là chuyển một bộ sưu tập các chuỗi đến một chế độ xem để hiển thị ở đó?

Trả lời

55

Thử sử dụng TempData. Nó giống như một đối tượng phiên một lần. Bạn đặt giá trị bạn muốn vào TempData, ngay lập tức chuyển hướng và nhận chúng ra. Có một writeup tốt ở đây: http://blogs.teamb.com/craigstuntz/2009/01/23/37947/

+0

Tôi đã thử ViewData nhưng không thể làm cho nó hoạt động. Cùng với TempData nhưng tôi chỉ cho nó một đoạn ngắn trước khi đi ngủ tối qua. Điều quan trọng nhất là, tôi thực sự muốn tránh những từ điển này và sử dụng đối tượng View Model mạnh mẽ được đánh máy – splatto

+1

Yea, nhưng đối tượng Model View của bạn - điều đó sẽ không dính xung quanh việc gõ mạnh HTTP 302. Bạn có thể dán mô hình vào TempData và bỏ nó ra. (Thành thật mà nói, tôi thấy dễ dàng hơn khi bỏ qua việc gõ khi sử dụng ASP.NET MVC, vì nó đơn giản là không làm tốt.) – MichaelGG

4

Sự cố với RedirectToAction là sự cố trở lại HTTP 302 và trình duyệt sau đó tự chạy và thực hiện yêu cầu HTTP hoàn toàn mới. Bạn có thể muốn xem xét sử dụng một cookie và/hoặc đối tượng phiên để duy trì dữ liệu giữa các yêu cầu.

2

Có vẻ như bạn' đang cố gắng làm:

public ActionResult UpdateContent(FormCollection form) { 
    ... 
    return View("Preview", _pagecontent); 
} 

Lưu ý rằng chuyển hướng được coi là "đá sạch" cho lông mày er (ngoại trừ những thứ như cookie auth). Bạn không được yêu cầu trình duyệt chuyển thông tin đến yêu cầu tiếp theo, vì yêu cầu tiếp theo sẽ có thể tự thực hiện. Tất cả những gì bạn cần làm là cho trình duyệt biết URL cần yêu cầu tiếp theo. Trong ASP.NET MVC, khi bạn chuyển đối số-đối tượng đến RedirectToAction, các thuộc tính công khai của đối tượng đó được nối thêm dưới dạng tham số chuỗi truy vấn vào URL được tạo.

+0

Lý do của tôi không sử dụng return View() là vì url sẽ hiển thị dạng xem gọi (AddContent), không phải là Chế độ xem được hiển thị (Xem trước). Khi người dùng nhấp vào nút "gửi", nó gọi cùng một hành động AddContent [Post] mà chỉ hiển thị chế độ xem trước, vì vậy sau đó tôi không thể nhấn hành động Xem trước [đăng]. – splatto

+0

Tại sao bạn đăng lên/MyController/AddContent? Tại sao không đăng lên/MyController/Preview? – yfeldblum

+0

Tôi cố gắng để có bài AddContent hành động của tôi để xem trước, nhưng khi tôi trở lại View ("Xem trước", _pagecontent) nó ám Preview nhưng url nói "/ Controller/AddContent". Sau đó, khi tôi nhấp vào nút để duy trì cơ sở dữ liệu, nó lại gọi hành động Addcontent post thay vì hành động của bài viết Preview. – splatto

7

Tham số thứ hai cho RedirectAction là routeValues, chứ không phải mô hình.

protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues); 

Hãy thử sử dụng TempData cho mô hình. Của nó cho sự bền bỉ dữ liệu giữa các chuyển hướng.

3

Điều này không hoạt động vì RedirectToAction thực sự gửi lại một Http 302 đến trình duyệt. Khi trình duyệt nhận được 302 này, nó sẽ yêu cầu một máy chủ mới yêu cầu trang mới. Yêu cầu mới, biến tạm thời mới.

Bạn cũng sẽ gặp phải sự cố này khi bạn cố lưu/chỉnh sửa/xóa nội dung nào đó và vì lý do nào đó bạn từ chối và bạn phải trả lại biểu mẫu cũ.

Vì vậy, thay vì:

return RedirectToAction("Preview", _pagecontent); 

Đặt logic Preview trong một phương pháp riêng biệt và chỉ gọi nó là:

return PreviewLogic(_pagecontent); 

Bạn cũng có thể sử dụng TempData [] dic để tồn tại dữ liệu cho yêu cầu tiếp theo như những người khác đã nói, nhưng sau đó bạn sẽ không tránh được 302 chuyến đi vòng bổ sung đến máy chủ.

10

Hãy cẩn thận khi sử dụng TempData. Nó hoạt động tốt trong một môi trường máy chủ duy nhất nhưng trong một môi trường đám mây nó có thể không hoạt động như mong đợi vì bạn không thể đảm bảo rằng yêu cầu sẽ nhấn cùng một máy. Điều này xảy ra vì TempData dựa vào phiên asp.net. Nhưng nếu bạn đang sử dụng trình quản lý phiên khác như SQL hoặc AppFabric Cache, nó sẽ hoạt động tốt.

0

Bạn không thể tạo 2 kết quả hành động có cùng tên và đánh dấu 1 trong số chúng bằng HttpPost?

public ActionResult UpdateContent(FormCollection preview = null) 
    { 
     return View(preview); 
    } 
    [HttpPost] 
    public ActionResult UpdateContent(FormCollection collection = null, bool preview = false) 
    { 
     if (preview) 
      return UpdateContent(collection); 
     else 
      return UpdateContent(null); 
    } 
Các vấn đề liên quan