2013-01-22 22 views
7

Tôi đang viết một asp.net 4.5 ứng dụng sử dụng các tính năng định tuyến mới. Tôi có một trang hiển thị một số thông tin về một mục. Trong sự kiện Page_Load tôi kiểm tra dữ liệu tuyến đường (id mặt hàng) và quyền của người dùng và nếu có điều gì đó không đúng (ví dụ: id dành cho mục đã xóa), tôi sử dụng Response.RedirectToRoute để gửi chúng đóng gói, quay lại trang chủ. Không vượt qua GO, không thu 200 đô la.Đúng cách để bỏ qua hành trang sau Response.RedirectToRoute

này có ý nghĩa hoàn hảo cho đến khi tôi đã cố gắng để truy cập vào một mục bị xóa và thay vì trang nhà tôi có một trang lỗi. Tôi đã làm một số đào và phát hiện ra rằng ngay cả sau khi tôi sử dụng RedirectToRoute (không giống như các tiêu chuẩn Redirect phương pháp) phần còn lại của mã trang continues to execute, mà ít nhất dường như lãng phí (kể từ khi tôi chỉ cần đi vứt bỏ kết quả) và ném lỗi khi dữ liệu cần thiết không tồn tại.

tôi đã làm một chút SO hơn khai thác và phát hiện ra không thể tin được đó là evilResponse.End(). Nó làm những gì tôi cần, nhưng ngay cả MSDN page cho tôi biết rằng Response.End là đứa con khốn của một ngôn ngữ bị nguyền rủa cổ xưa và không phù hợp để nhìn thấy ánh sáng ban ngày. Các phản đối chính có vẻ là một thực tế rằng Response.End ném một ngoại lệ, và đó là xấu cho hiệu suất. Tôi không phải là nhà phát triển có kinh nghiệm nhất, vì vậy tôi không hiểu vấn đề hoàn toàn, nhưng tôi gặp khó khăn khi tin rằng việc ném một ngoại lệ là đắt hơn tải toàn bộ trang web. Các workarounds có vẻ khá phức tạp và quá mức cho một nhiệm vụ rất đơn giản, đặc biệt là vì hầu hết các trang yêu cầu một số loại kiểm tra tính hợp lệ.

Tôi phải làm gì trong tình huống này? Sử dụng Response.End và cầu xin sự tha thứ cho sự xấc xược của tôi? Sỏi cùng nhau một số cách giải quyết xấu xí? Hoặc là quan điểm của tôi về vấn đề tất cả các sai lầm để bắt đầu với? Tôi thực sự muốn biết.

Cập nhật: Bây giờ tôi đã nghĩ nó hơn một chút nữa, tôi tự hỏi, nếu tôi có quan điểm sai về vấn đề này. Có lẽ chuyển hướng ngay lập tức không phải là phản hồi tốt nhất cho trải nghiệm người dùng. Tôi sẽ tốt hơn hết gói tất cả các điều khiển trong một bảng điều khiển, và sử dụng một cái gì đó như thế này?

Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init 
    'Validation Code 
    If notValid Then 
     ControlsPanel.Visible = false 
     ErrorPanel.Visible = true 
    End If 
End Sub 

Trả lời

3

Tôi có thể ra ngoài bằng cách không trả lời câu hỏi trực tiếp, nhưng tôi thích nhìn thấy bản cập nhật của bạn về trải nghiệm người dùng. Tôi thích cách tiếp cận được đề xuất của bạn.

tôi muốn cung cấp cho một lỗi 410 cho id mà không phải là hợp lệ và mở rộng nó một chút với (dịch từ C#):

Protected Sub ItemDoesNotExist() 
'item does not exist, serve up error page 
ControlsPanel.Visible = False 
ErrorPanel.Visible = True 

'add meta tags for noindex 
Dim mymeta As New HtmlMeta() 
mymeta.Name = "robots" 
mymeta.Content = "noindex" 
Page.Header.Controls.Add(mymeta) 

'RESPOND WITH A 410 
Response.StatusCode = 410 
Response.Status = "410 Gone" 
Response.StatusDescription = "Gone" 
Response.TrySkipIisCustomErrors = True 
'important for IIS7, otherwise the Custom error page for 404 shows. 
Page.Title = "item gone" 
End Sub 
+0

Cảm ơn đã theo lên. Tôi không nhận ra rằng bạn có thể trả lời bằng mã lỗi và vẫn tải trang. Tôi chắc chắn sẽ ghi nhớ điều này trong tương lai. –

9

RedirectToRoute thực sự là kết thúc tốt đẹp Response.Redirect qua false cho kết thúc theo yêu cầu - do đó, yêu cầu tiếp tục. Bạn có thể sử dụng HttpApplication.CompleteRequest làm cuộc gọi ngay để chấm dứt yêu cầu để các sự kiện ứng dụng tiếp theo sẽ không được gọi.

Response.End (và các biến thể chuyển hướng khác) ném ThreadAbortException để hủy bỏ chuỗi xử lý yêu cầu thực sự là cách xấu cách ngừng xử lý yêu cầu. Trong thế giới .NET, xử lý ngoại lệ luôn được coi là đắt tiền vì CLR sau đó cần tìm kiếm ngăn xếp tất cả các con đường cho các khối xử lý ngoại lệ, tạo ngăn xếp dấu vết, vv IMO, CompleteRequest được giới thiệu trong .NET 1.1. đặt cờ trong mã cơ sở hạ tầng ASP.NET để bỏ qua xử lý tiếp theo trừ sự kiện EndRequest.

Tuy nhiên, một (và tốt hơn) Cách thứ nhất là sử dụng Server.Transfer và tránh client khứ hồi để cài đặt chuyển hướng tất cả lại với nhau. Chỉ có vấn đề là khách hàng sẽ không thấy URL được chuyển hướng trong thanh địa chỉ của trình duyệt. Tôi thường thích phương pháp này.

EDIT
CompleteRequest sẽ không bao giờ làm việc trong trường hợp trang mà các sự kiện trang tiếp theo sẽ được vẫn gọi bởi vì trang bị một bộ xử lý, tất cả các sự kiện của nó sẽ xảy ra trong một ứng dụng sự kiện ProcessRequest duy nhất (và hiện tại).Vì vậy, cách duy nhất dường như là đặt cờ và kiểm tra cờ đó trong ghi đè chẳng hạn như Render, PreRender, RaisePostBackEvent v.v.

Từ quan điểm bảo trì, có ý nghĩa để có chức năng như vậy trong lớp cơ sở (ví dụ: duy trì cờ, cung cấp CompleteRequest phương thức cho các lớp con và ghi đè phương thức sự kiện vòng đời). Ví dụ:

internal class PageBase: System.Web.UI.Page 
{ 
    bool _requestCompleted; 

    protected void CompleteRequest() 
    { 
     Context.ApplicationInstance.CompleteRequest(); 
     _requestCompleted = true; 
    } 

    protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, 
    string eventArgument) 
    { 
     if (_requestCompleted) return; 
     base.RaisePostBackEvent(sourceControl, eventArgument); 
    } 

    protected internal override void Render(HtmlTextWriter writer) 
    { 
     if (_requestCompleted) return; 
     base.Render(writer); 
    } 

    protected internal override void OnPreRender(EventArgs e) 
    { 
     if (_requestCompleted) return; 
     base.OnPreRender(e); 
    } 

    ... and so on 
} 
+1

Cám ơn câu trả lời của bạn. Tôi nhận thấy rằng 'CompleteRequest' đã được đề xuất như là một lựa chọn tốt hơn, nhưng nó cũng tiếp tục thực hiện tất cả các mã trên trang. Các điều khiển khác nhau trên trang lấy dữ liệu của chúng từ mục và khi nó không tồn tại, chúng sẽ ném lỗi, vì vậy tôi nhận được trang lỗi thay vì chuyển hướng. Tôi có thể đi qua và kiểm tra tính hợp lệ trên mọi phương pháp, nhưng điều đó có vẻ _rather_ không cần thiết và ít bảo trì hơn. –

+0

Tôi thấy nó thú vị khi bạn đề cập đến 'Server.Transfer'. Mặc dù tôi đánh giá cao lợi ích của việc tránh một chuyến đi khứ hồi, tôi không cảm thấy phương pháp đó sẽ hoạt động tốt cho mục đích của mình vì URL hiện tại của người dùng không hợp lệ. Tôi cũng đã đọc rằng 'Server.Transfer' gọi' Response.End' và tôi không thấy quá tải của hàm để tránh điều này. –

+2

@probackpacker, vui lòng chấp nhận lời xin lỗi của tôi! 'CompleteRequest' ảnh hưởng đến các sự kiện đường ống ứng dụng, nhưng sự kiện trình xử lý hiện tại sẽ tiếp tục. Sẽ không có cách nào khác ngoài việc sử dụng cờ để kiểm tra trong trang - từ quan điểm bảo trì, bạn có thể trích xuất nó thành lớp trang cơ sở có thể tái sử dụng (xem phần chỉnh sửa của tôi). – VinayC

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