2009-05-29 78 views
96

Tôi đang thực hiện một chương trình đơn giản trong visual C# 2005 tra cứu một biểu tượng cổ phiếu trên Yahoo! Tài chính, tải xuống dữ liệu lịch sử và sau đó vẽ lịch sử giá cho biểu tượng mã được chỉ định.C# Làm cách nào để kiểm tra xem URL có tồn tại/hợp lệ không?

Tôi biết URL chính xác mà tôi cần để thu thập dữ liệu và nếu người dùng nhập biểu tượng chứng khoán hiện có (hoặc ít nhất một bằng dữ liệu trên Yahoo Finance), nó hoạt động hoàn toàn tốt. Tuy nhiên, tôi có một lỗi thời gian chạy nếu người dùng tạo ra một biểu tượng ticker, khi chương trình cố gắng lấy dữ liệu từ một trang web không tồn tại.

Tôi đang sử dụng lớp WebClient và sử dụng chức năng DownloadString. Tôi đã xem xét tất cả các hàm thành viên khác của lớp WebClient, nhưng không thấy bất cứ điều gì tôi có thể sử dụng để kiểm tra một URL.

Tôi làm cách nào để thực hiện việc này?

+1

cập nhật để hiển thị C# 2.0 (VS2005) sử dụng –

Trả lời

97

Bạn có thể gửi yêu cầu "HEAD" thay vì "GET"?

(chỉnh sửa) - lol! Có vẻ như tôi đã done this before!; thay đổi thành wiki để tránh các cáo buộc về việc tái phạm. Vì vậy, để kiểm tra một URL mà không cần phải tải về các nội dung:

// using MyClient from linked post 
using(var client = new MyClient()) { 
    client.HeadOnly = true; 
    // fine, no content downloaded 
    string s1 = client.DownloadString("http://google.com"); 
    // throws 404 
    string s2 = client.DownloadString("http://google.com/silly"); 
} 

Bạn sẽ try/catch quanh DownloadString để kiểm tra lỗi; không có lỗi? Nó tồn tại ...


Với C# 2.0 (VS2005):

private bool headOnly; 
public bool HeadOnly { 
    get {return headOnly;} 
    set {headOnly = value;} 
} 

using(WebClient client = new MyClient()) 
{ 
    // code as before 
} 
+0

tốt ý tưởng với việc chuyển sang wiki trong những trường hợp này; sẽ ghi nhớ điều đó để sử dụng trong tương lai ... –

+0

FWIW - Không chắc liệu điều đó có thực sự giải quyết được vấn đề (không phải là phía máy khách hành vi khác) vì bạn chỉ đơn giản là thay đổi phương thức HTTP. Phản hồi từ máy chủ sẽ phụ thuộc rất nhiều vào cách mã hóa logic và có thể không hoạt động tốt cho một dịch vụ động như giá cổ phiếu. Đối với tài nguyên tĩnh (ví dụ: hình ảnh, tệp, v.v.) HEAD thường hoạt động như được quảng cáo vì nó được đưa vào máy chủ. Nhiều lập trình viên không yêu cầu HEAD rõ ràng vì trọng tâm thường là POST và GET. YMMV –

+0

Xin lỗi vì đã mất quá nhiều thời gian để chọn câu trả lời ... Tôi đã bị bỏ rơi với trường học và công việc và loại quên bài đăng này. Là một sidenote, tôi không thể nhận được giải pháp của bạn để làm việc vì tôi đang sử dụng Visual Studio 2005 mà không có loại 'var'. Tôi đã không làm việc trên dự án này trong nhiều tháng, nhưng có sửa chữa đơn giản cho thực tế đó? Ngoài ra khi tôi đã cố gắng để thực hiện giải pháp của bạn, tôi nhớ rằng nó đã nổi giận với tôi để cố gắng xác định tài sản HeadOnly không có mã trong các định nghĩa 'get' và 'set'. Hoặc có lẽ tôi đã làm sai điều gì đó. Cảm ơn sự giúp đỡ của bạn! –

0

máy chủ Web đáp ứng với một mã trạng thái HTTP cho thấy kết quả của yêu cầu ví dụ 200 (đôi khi 202) nghĩa là thành công, 404 - không tìm thấy vv (xem here). Giả sử phần địa chỉ máy chủ của URL là chính xác và bạn không nhận được thời gian chờ của ổ cắm, ngoại lệ rất có thể cho bạn biết mã trạng thái HTTP khác với 200. Tôi khuyên bạn nên kiểm tra lớp ngoại lệ và xem liệu ngoại lệ có mang hay không mã trạng thái HTTP.

IIRC - Cuộc gọi được đề cập sẽ phát ra WebException hoặc hậu duệ. Kiểm tra tên lớp để xem tên nào và kết thúc cuộc gọi trong khối thử để bẫy điều kiện.

+2

Thực ra, mọi thứ trong phạm vi 200-299 nghĩa là thành công, IIRC –

+0

Marc, bạn hoàn toàn chính xác. Tôi cố tình tránh vào khái niệm "loại lỗi" (ví dụ: 5xx, 4xx, 3xx, 2xx vv) vì nó sẽ mở ra toàn bộ một loại sâu khác. Ngay cả việc xử lý các mã tiêu chuẩn (200, 302, 404, 500 vv) cũng tốt hơn nhiều so với việc bỏ qua các mã hoàn toàn. –

7

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, bạn có thể sử dụng một phương pháp nhỏ như thế này để cung cấp cho bạn những kết quả của bài kiểm tra URL của bạn:

WebRequest webRequest = WebRequest.Create(url); 
WebResponse webResponse; 
try 
{ 
    webResponse = webRequest.GetResponse(); 
} 
catch //If exception thrown then couldn't get response from address 
{ 
    return 0; 
} 
return 1; 

Bạn có thể quấn các mã trên trong một phương pháp và sử dụng nó để thực hiện xác thực. Tôi hy vọng điều này sẽ trả lời câu hỏi bạn đang hỏi.

+1

Có, có lẽ bạn có thể tinh chỉnh giải pháp bằng cách phân biệt giữa các trường hợp khác nhau (lỗi kết nối TCP - máy chủ từ chối kết nối, 5xx - Đã xảy ra sự cố nghiêm trọng, 404 - Không tìm thấy tài nguyên, v.v.).Hãy xem xét thuộc tính Trạng thái của WebException;) –

+0

Rất tốt David! Điều đó sẽ cung cấp cho chúng tôi phản hồi chi tiết hơn để chúng tôi có thể xử lý lỗi nghiêm ngặt hơn. –

+1

Cảm ơn. Quan điểm của tôi là có một số lớp để hành tây này, mỗi trong số đó có thể ném một cờ lê vào các công trình (.Net Framework, DNS Nghị quyết, kết nối TCP, mục tiêu Web Server, mục tiêu ứng dụng, vv). IMHO một thiết kế tốt sẽ có thể phân biệt giữa các điều kiện thất bại khác nhau để cung cấp phản hồi thông tin và chẩn đoán có thể sử dụng. Cho phép cũng không quên HTTP có mã trạng thái vì một lý do;) –

113

Dưới đây là một việc thực hiện các giải pháp này:

using System.Net; 

/// 
/// Checks the file exists or not. 
/// 
/// The URL of the remote file. 
/// True : If the file exits, False if file not exists 
private bool RemoteFileExists(string url) 
{ 
    try 
    { 
     //Creating the HttpWebRequest 
     HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; 
     //Setting the Request method HEAD, you can also use GET too. 
     request.Method = "HEAD"; 
     //Getting the Web Response. 
     HttpWebResponse response = request.GetResponse() as HttpWebResponse; 
     //Returns TRUE if the Status code == 200 
     response.Close(); 
     return (response.StatusCode == HttpStatusCode.OK); 
    } 
    catch 
    { 
     //Any exception will returns false. 
     return false; 
    } 
} 

Từ: http://www.dotnetthoughts.net/2009/10/14/how-to-check-remote-file-exists-using-c/

+1

Tôi đang sử dụng mã này để kiểm tra xem một loạt các hình ảnh có tồn tại hay không và nó khá chậm (vài giây cho mỗi URL). Có ai biết nếu đây là một vấn đề với mã này, hoặc chỉ là một thực tế của cuộc sống khi thực hiện các loại cuộc gọi? – ssmith

+2

+1 cho mã. Đó là dễ đọc hơn mà không có ý kiến ​​mặc dù, IMO ... –

+1

Thích mã: nó là sạch sẽ và hoạt động ổn định. – Demir

2

giải pháp này có vẻ dễ dàng để làm theo:

public static bool isValidURL(string url) { 
    WebRequest webRequest = WebRequest.Create(url); 
    WebResponse webResponse; 
    try 
    { 
     webResponse = webRequest.GetResponse(); 
    } 
    catch //If exception thrown then couldn't get response from address 
    { 
     return false ; 
    } 
    return true ; 
} 
+1

đừng quên đóng webResponse, nếu không, thời gian phản hồi sẽ tăng lên mỗi khi bạn gọi phương thức – Madagaga

25

Những giải pháp này là khá tốt, nhưng họ quên có thể có các mã trạng thái khác hơn 200 OK.Đây là một giải pháp mà tôi đã sử dụng trên môi trường sản xuất để theo dõi tình trạng và như vậy.

Nếu có chuyển hướng url hoặc một số điều kiện khác trên trang đích, lợi nhuận sẽ là true bằng phương pháp này. Ngoài ra, GetResponse() sẽ ném một ngoại lệ và do đó bạn sẽ không nhận được một StatusCode cho nó. Bạn cần phải bẫy ngoại lệ và kiểm tra một ProtocolError.

Bất kỳ mã trạng thái 400 hoặc 500 nào đều trả về false. Tất cả những người khác trở lại sự thật. Mã này có thể dễ dàng sửa đổi cho phù hợp với nhu cầu của bạn đối với các mã trạng thái cụ thể.

/// <summary> 
/// This method will check a url to see that it does not return server or protocol errors 
/// </summary> 
/// <param name="url">The path to check</param> 
/// <returns></returns> 
public bool UrlIsValid(string url) 
{ 
    try 
    { 
     HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; 
     request.Timeout = 5000; //set the timeout to 5 seconds to keep the user from waiting too long for the page to load 
     request.Method = "HEAD"; //Get only the header information -- no need to download any content 

     HttpWebResponse response = request.GetResponse() as HttpWebResponse; 

     int statusCode = (int)response.StatusCode; 
     if (statusCode >= 100 && statusCode < 400) //Good requests 
     { 
      return true; 
     } 
     else if (statusCode >= 500 && statusCode <= 510) //Server Errors 
     { 
      log.Warn(String.Format("The remote server has thrown an internal error. Url is not valid: {0}", url)); 
      return false; 
     } 
    } 
    catch (WebException ex) 
    { 
     if (ex.Status == WebExceptionStatus.ProtocolError) //400 errors 
     { 
      return false; 
     } 
     else 
     { 
      log.Warn(String.Format("Unhandled status [{0}] returned for url: {1}", ex.Status, url), ex); 
     } 
    } 
    catch (Exception ex) 
    { 
     log.Error(String.Format("Could not test url {0}.", url), ex); 
    } 
    return false; 
} 
+1

Tôi sẽ thêm rằng một số mã trạng thái trong phạm vi 3xx sẽ thực sự gây ra lỗi. 304 Không được sửa đổi trong trường hợp nào bạn nên xử lý trong khối catch của bạn – RobV

+3

Chỉ gặp vấn đề kéo-ra-lông-ra-bằng với cách tiếp cận này: 'HttpWebRequest' không thích nó nếu bạn không' .Close() ' đối tượng 'response' trước khi bạn cố tải xuống bất kỳ thứ gì khác. Mất nhiều giờ để tìm cái đó! – jbeldock

+2

'HttpWebResponse' đối tượng ** nên được đặt trong' using' block ** vì nó triển khai 'IDisposable' cũng sẽ đảm bảo đóng kết nối. Điều này có thể gây ra vấn đề như @jbeldock, đã phải đối mặt. – Habib

0

tôi có cách đơn giản hơn để xác định thời tiết url hợp lệ.

if (Uri.IsWellFormedUriString(uriString, UriKind.RelativeOrAbsolute)) 
{ 
    //... 
} 
+3

Không, phương pháp này không kiểm tra xem url có thực sự truy cập hay không. Nó thậm chí còn trả về true khi Uri.IsWellFormedUriString ("http://192.168.1.421/", ...), sử dụng url không chính xác rõ ràng – zhaorufei

2

Dưới đây là một tùy chọn

public static bool UrlIsValid(string url) 
{ 
    bool br = false; 
    try { 
     IPHostEntry ipHost = Dns.Resolve(url); 
     br = true; 
    } 
    catch (SocketException se) { 
     br = false; 
    } 
    return br; 
} 
+2

Điều đó có thể hữu ích để kiểm tra xem máy chủ có tồn tại hay không. Câu hỏi rõ ràng là không lo lắng về việc liệu máy chủ có tồn tại hay không. Nó có liên quan đến việc xử lý một đường dẫn HTTP xấu * do máy chủ được biết là tồn tại và được sử dụng tốt *. – binki

0

Tiếp theo từ các ví dụ đã đưa ra, tôi muốn nói, đó là thực hành tốt nhất cũng để bọc các phản ứng trong một sử dụng như thế này

public bool IsValidUrl(string url) 
    { 
     try 
     { 
      var request = WebRequest.Create(url); 
      request.Timeout = 5000; 
      request.Method = "HEAD"; 

      using (var response = (HttpWebResponse)request.GetResponse()) 
      { 
       response.Close(); 
       return response.StatusCode == HttpStatusCode.OK; 
      } 
     } 
     catch (Exception exception) 
     { 
      return false; 
     } 
    } 
2

Hãy thử điều này (Hãy chắc chắn rằng bạn sử dụng System.Net):

public bool checkWebsite(string URL) { 
    try { 
     WebClient wc = new WebClient(); 
     string HTMLSource = wc.DownloadString(URL); 
     return true; 
    } 
    catch (Exception) { 
     return false; 
    } 
} 

Khi chức năng checkWebsite() được gọi, nó sẽ cố lấy mã nguồn của URL được truyền vào nó. Nếu nó nhận được mã nguồn, nó trả về true. Nếu không, sẽ trả về false.

Mã số Ví dụ:

//The checkWebsite command will return true: 
bool websiteExists = this.checkWebsite("https://www.google.com"); 

//The checkWebsite command will return false: 
bool websiteExists = this.checkWebsite("https://www.thisisnotarealwebsite.com/fakepage.html"); 
Các vấn đề liên quan