2015-07-31 19 views
10

Để bắt đầu, đây là một cuộc thảo luận nếu có ai trong số các bạn làm một điều như yêu cầu hủy trong bộ điều khiển WebAPI (có thể cũng áp dụng cho MVC).Asp.net WebAPI: Hủy bỏ (hủy bỏ) yêu cầu

Điều tôi ngụ ý cụ thể là một kịch bản như sau: Một khách hàng (trình duyệt thường) bắt đầu yêu cầu, điều hướng đi hoặc tổng quát hơn, hủy yêu cầu vì bất kỳ lý do gì. Bây giờ, yêu cầu bị hủy bỏ ở phía khách hàng và sẽ không còn được xem xét. Nhưng ở phía máy chủ theo yêu cầu vẫn đang diễn ra và thường có thể làm 2 điều đặc biệt thú vị:

  • Thực hiện một (nặng) DB-Query
  • Thực hiện một (nặng) gọi dịch vụ khác phục vụ

Và tất cả không có gì cuối cùng (ít nhất là khi nó là một tác dụng phụ miễn phí đọc hoạt động ít nhất).

Có ai đó xử lý việc hủy cuộc gọi truy vấn/dịch vụ đang diễn ra trong trường hợp này không?

Những gì tôi biết là một CancellationToken có thể được thông qua trong API-Controller (mặc dù tôi không thể làm cho nó hoạt động để hủy bỏ được thực sự yêu cầu khi hủy bỏ từ khách hàng). Lý do hủy bỏ này, sẽ cần phải được chuyển xuống tất cả các tầng thấp hơn để xử lý việc hủy bỏ các cuộc gọi dịch vụ và DB.

+0

điều này có thể không trả lời đầy đủ câu hỏi của bạn, nhưng hãy xem http://stackoverflow.com/questions/19010856/should-we-use-cancellationtoken-with-mvc-web-api-controllers – David

+0

Nghe có vẻ thú vị . Nó có vẻ như nó có thể được quản lý để sử dụng CancellationToken như một tham số (điều này tôi biết) và đặc biệt là nó đã bị hủy bỏ bởi khuôn khổ. – cmart

Trả lời

6

Trong khi tại thời điểm viết WebAPI không trực tiếp hỗ trợ hủy, API OWIN hoàn toàn thực hiện. Nếu bạn đang sử dụng WebAPI 2.0, bạn sẽ chạy trên đầu OWIN và sẽ có thể truy cập ngữ cảnh thông qua trình bao bọc của Microsoft bằng cách sử dụng phương thức mở rộng GetOwinContext().

Thuận tiện cho việc hủy được tuyên truyền bằng cách sử dụng giá trị CancellationToken được hiển thị qua thuộc tính CallCancelled của số OwinRequest. Bạn có thể đặt tất cả những thứ này lại với nhau để nhận mã thông báo bên trong một phương thức điều khiển:

public async Task Get() 
{ 
    var cancellation = Request.GetOwinContext().Request.CallCancelled; 

    await database.FooAsync(cancellation); 
} 

Đó là điều khá xấu xí. Bạn sẽ phải thực hiện cuộc gọi này theo mọi phương thức cần xử lý việc hủy và nó không hoạt động tốt với tương lai được đề xuất mà WebAPI sẽ cung cấp cho bạn CancellationToken này. Thay vào đó, nó sẽ không đẹp hơn nếu chúng ta có thể biến nó thành một tham số?

public async Task Get(CancellationToken cancellation) 
{ 
    await database.FooAsync(cancellation); 
} 

Để làm điều này, bạn có thể tạo một tham số tùy chỉnh ràng buộc mà grabs CancellationToken từ bối cảnh OWIN:

public class OwinCancellationTokenBinding : HttpParameterBinding 
{ 
    public OwinCancellationTokenBinding(HttpParameterDescriptor parameter) 
     : base(parameter) 
    { 
    } 

    public override Task ExecuteBindingAsync(
     ModelMetadataProvider metadataProvider, 
     HttpActionContext actionContext, 
     CancellationToken cancellationToken) 
    { 
     actionContext.ActionArguments[Descriptor.ParameterName] 
      = actionContext.Request.GetOwinContext().Request.CallCancelled; 

     return Task.FromResult<object>(null); 
    } 
} 

Để sử dụng, bạn có thể đăng ký các ràng buộc với HttpConfiguration sử dụng bộ sưu tập ParameterBindingRules của nó :

config.ParameterBindingRules.Add(p 
    => p.ParameterType == typeof(CancellationToken) 
    ? new OwinCancellationTokenBinding (p) 
    : null); 

Quy tắc này khớp với bất kỳ thông số nào thuộc loại CancellationToken. Bạn có thể tạo bất kỳ quy tắc nào tại đây phù hợp với các tham số bạn muốn cung cấp giá trị này.

+1

Cảm ơn bạn! Nhưng không phải là điều này được hỗ trợ ra khỏi hộp?Khi một CancellationToken được sử dụng như tham số cuối cùng nó được thiết lập bởi đường dẫn webapi. tham khảo: https://books.google.at/books?id=FVMnCgAAQBAJ&pg=PA45&lpg=PA45&dq=cancellationtoken+parameter+asp.net+web+api&source=bl&ots=gcdA_GNuZh&sig=utOt1UGAEd8p7q8g2YmneI_2SNc&hl=de&sa=X&ved=0CCQQ6AEwAWoVChMI1ufg-vSFxwIVBY4sCh2YhA9U# v = onepage & q = cancellationtoken% 20parameter% 20asp.net% 20web% 20api & f = false (Tôi hy vọng liên kết này tiếp tục hoạt động) – cmart

+0

Sau đó, có vẻ như tôi đã làm việc về thông tin cũ. –

+1

Vâng, ý tưởng của bạn đã được triển khai! Có những người thực sự thông minh suy nghĩ về những chủ đề này tại microsoft, hãy tự hào! – cmart