2011-01-07 55 views
7

Tôi đang cố gắng để có được asp.net để lưu trữ ViewState trong phiên chứ không phải là bulking lên html.Bắt asp.net để lưu trữ ViewState trong phiên chứ không phải bulking lên html

Bây giờ tôi đã đọc rằng asp.net đi kèm với SessionPageStatePersister có thể được sử dụng thay cho HiddenFieldPageStatePersister mặc định để thực hiện việc này. Tôi đã tự hỏi làm thế nào tôi đi về thả nó vào?

Đây là những gì tôi đã có cho đến nay: Tôi nghĩ rằng tôi cần phải tạo một PageAdapter trả về một SessionPageStatePersister từ phương pháp GetStatePersister của nó, và bằng cách nào đó có được trang để sử dụng trang này. Nhưng Page.PageAdapter chỉ có một getter, vì vậy tôi không chắc chắn làm thế nào bạn thiết lập nó.

Xem tiêu đề 'nhận xét' ở đây: http://msdn.microsoft.com/en-us/library/system.web.ui.hiddenfieldpagestatepersister.aspx

Cảm ơn!

+0

đã coi bạn lưu trữ ViewState trong DB thay vì phiên, điều này sẽ dễ dàng hơn và cũng có quy mô tốt hơn nhiều – Daveo

+0

RPM: viewstate đã được tuần tự hóa nên không có sự khác biệt. RAM trên máy chủ của tôi nhanh hơn rất nhiều so với việc gửi 100kb viewstate cả hai cách trên các kết nối mạng Úc. – Chris

+0

daveo: Db sẽ chậm hơn ram. Chia tỷ lệ không phải là vấn đề - không phải loại trang web đó. – Chris

Trả lời

5

Để sử dụng lớp PageAdapter tùy chỉnh của bạn, bạn phải đăng ký nó với tệp .browser. Bạn cần thêm (nếu bạn chưa có) thư mục App_Browsers. Sau đó, thêm tệp .browser theo XML

<browsers> 
    <browser refID="Default"> 
     <controlAdapters> 
      <adapter controlType="System.Web.UI.Page" adapterType="{Your adapter type}" /> 
     </controlAdapters> 
    </browser> 
</browsers> 

thay thế {Loại bộ điều hợp của bạn} bằng loại bộ điều hợp của bạn.

Thông tin khác here

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn, đã làm việc cho tôi. Cuối cùng, với phương thức này và sử dụng lớp SessionPageStatePersister, nó không thực sự làm giảm kích thước ViewState ở tất cả (và i * đã * phá vỡ nó để đảm bảo nó được gọi). Tôi nghĩ rằng nó chỉ là lưu trữ các pagestate, không phải là viewstate, do đó, không thực sự là một tiết kiệm lớn. Oh well. Dù sao cũng cảm ơn bạn! – Chris

8

Bạn có chắc chắn muốn thực hiện việc này không? Có sự cố

  1. Làm cách nào để tách biệt từng trang? Chắc chắn, bạn có thể thêm tiền tố tên tiểu bang phiên với trang, ví dụ: Phiên ["/ default.aspx-Viewstate"] nhưng điều gì sẽ xảy ra khi người dùng có nhiều phiên bản của một trang mở?
  2. Vì vậy, để giải quyết rằng bạn đặt một trường ẩn với, giả sử, GUID trong mỗi trang, sau đó bạn sử dụng làm khóa. Vì vậy, kích thước phiên của bạn tăng lên. Và phát triển. Và phát triển. Làm thế nào bạn sẽ biết nếu/khi bạn có thể loại bỏ mọi thứ một cách an toàn?

Nếu bạn nhấn mạnh vào việc đọc phần này, tất cả những gì bạn cần làm là lấy một lớp từ trang và ghi đè LoadPageStateFromPersistenceMedium() và SavePageStateToPersistenceMedium(). Nhưng bạn sẽ ghét bản thân và xé nó ra.

Chỉ cần đảm bảo rằng bạn đã bật tính năng nén HTTP tại máy chủ của mình và vui lòng lo lắng về điều gì đó khác thay thế.

+1

câu cuối cùng làm tôi cười khúc khích, nhưng điều đó hoàn toàn đúng. gzip sẽ tạo nên một thế giới của viewstate. –

+0

1: Tôi cho rằng sẽ được xử lý bằng cách xây dựng trong lớp SessionPageStatePersister – Chris

+0

2: Cuộc gọi công bằng. Tôi chắc chắn tôi sẽ nghĩ về điều gì đó. Có thể là một mảng tròn hay gì đó. – Chris

7

Đối với những gì nó có giá trị, đây là mã tôi đã kết thúc bằng cách sử dụng để giải quyết vấn đề lớn hình ảnh trong tầm tay: di chuyển viewstate ra khỏi html. Chỉ cần bật này vào mypage.aspx.cs của bạn:

// Inspired by: http://aspalliance.com/72 
const string ViewStateFieldName = "__VIEWSTATEKEY"; 
const string RecentViewStateQueue = "RecentViewStateQueue"; 
const int RecentViewStateQueueMaxLength = 5; 

protected override object LoadPageStateFromPersistenceMedium() 
{ 
    // The cache key for this viewstate is stored where the viewstate normally is, so grab it 
    string viewStateKey = Request.Form[ViewStateFieldName] as string; 
    if (viewStateKey == null) return null; 

    // Grab the viewstate data from the cache using the key to look it up 
    string viewStateData = Cache[viewStateKey] as string; 
    if (viewStateData == null) return null; 

    // Deserialise it 
    return new LosFormatter().Deserialize(viewStateData); 
} 

protected override void SavePageStateToPersistenceMedium(object viewState) 
{ 
    // Serialise the viewstate information 
    StringBuilder _viewState = new StringBuilder(); 
    StringWriter _writer = new StringWriter(_viewState); 
    new LosFormatter().Serialize(_writer, viewState); 

    // Give this viewstate a random key 
    string viewStateKey = Guid.NewGuid().ToString(); 

    // Store the viewstate in the cache 
    Cache.Add(viewStateKey, _viewState.ToString(), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(Session.Timeout), CacheItemPriority.Normal, null); 

    // Store the viewstate's cache key in the viewstate hidden field, so on postback we can grab it from the cache 
    ClientScript.RegisterHiddenField(ViewStateFieldName, viewStateKey); 

    // Some tidying up: keep track of the X most recent viewstates for this user, and remove old ones 
    var recent = Session[RecentViewStateQueue] as Queue<string>; 
    if (recent == null) Session[RecentViewStateQueue] = recent = new Queue<string>(); 
    recent.Enqueue(viewStateKey); // Add this new one so it'll get removed later 
    while (recent.Count > RecentViewStateQueueMaxLength) // If we've got lots in the queue, remove the old ones 
    Cache.Remove(recent.Dequeue()); 
} 

Và đối với một cách siêu đơn giản của việc sử dụng các SessionPageStatePersister, một lần nữa đặt này trong mypage.aspx.cs của bạn:

protected override PageStatePersister PageStatePersister 
{ 
    get 
    { 
     return new SessionPageStatePersister(this); 
    } 
} 
+1

Năm năm sau và mã này vẫn là mì ống sao chép xứng đáng. Tôi đã có thể đặt điều này vào một trình chuyển đổi VB.NET và dán nó vào trang của tôi sau khi chỉ một vài chỉnh sửa nhỏ. Tôi không bao giờ khuyên bạn nên lưu trữ ViewState trong bộ nhớ máy chủ, nhưng điều này hoạt động tốt như một giải pháp tạm thời khi chúng tôi viết lại ứng dụng WebForms 15 tuổi của chúng tôi để sử dụng Angular và WebAPI. Chỉ cần đảm bảo dọn dẹp chế độ xem được lưu trong bộ nhớ cache khi thực hiện thay vì đợi nó hết hạn. – oscilatingcretin

+0

@oscilatingcretin Vì vậy, ngay trước khi bạn quay trở lại ViewState trong LoadPageStateFromPersistenceMedium(), làm Cache.Remove (viewStateKey)? Tôi lấy nó là an toàn để làm ở đó như là một viewstate mới được tạo ra cho callbacks tiếp theo? Nó có lẽ vẫn là một ý tưởng tốt để xóa những cái cũ trong SavePageStateToPersistenceMedium() – Radderz

+0

Bỏ qua gợi ý cuối cùng của tôi. Bạn không thể xóa sau khi được tải; nếu người dùng làm mới trang đăng lại dữ liệu biểu mẫu giống nhau thì sao? Nó sẽ mất trạng thái của trang đó. – Radderz

Các vấn đề liên quan