Bagaimana cara mengakses metode HttpServerUtility.MapPath di Thread atau Timer?

88

Saya menggunakan System.Timers.Timeraplikasi Asp.Net saya dan saya perlu menggunakan HttpServerUtility.MapPathmetode yang tampaknya hanya tersedia melalui HttpContext.Current.Server.MapPath. Masalahnya adalah bahwa HttpContext.Currentadalah nullketika Timer.Elapsedperistiwa kebakaran.

Apakah ada cara lain untuk mendapatkan referensi ke objek HttpServerUtility? Saya bisa menyuntikkannya ke konstruktor kelas saya. Apakah ini aman? Bagaimana saya bisa yakin itu tidak akan Mengumpulkan Sampah di akhir permintaan saat ini?

Terima kasih!

Costo
sumber

Jawaban:

142

Ini mungkin untuk digunakan HostingEnvironment.MapPath()sebagai penggantiHttpContext.Current.Server.MapPath()

Saya belum mencobanya di thread atau acara pengatur waktu.


Beberapa solusi (tidak layak) yang saya pertimbangkan;

  • Satu-satunya metode yang saya pedulikan HttpServerUtilityadalah MapPath. Jadi sebagai alternatif saya bisa menggunakan AppDomain.CurrentDomain.BaseDirectorydan membangun jalur saya dari ini. Tetapi ini akan gagal jika aplikasi Anda menggunakan direktori virtual (Milik saya melakukannya).

  • Pendekatan lain: Tambahkan semua jalur yang saya butuhkan ke Globalkelas. Selesaikan jalur ini Application_Start.

Costo
sumber
1
Namun perlu diperhatikan bahwa hal di atas tidak berfungsi di versi IIS yang lebih baru. Di IIS7, permulaan aplikasi dapat dipanggil di luar permintaan http. Yaitu, contoh kode. Saya yakin HostingEnvironment.MapPath () akan tetap berfungsi seperti sebelumnya.
Robba
Tetapi HostingEnvironment.MapPath () memberikan kesalahan jika Anda meneruskannya dan mengosongkan string untuk mendapatkan jalur folder secara langsung ... HttpContext.Current.Server.MapPath (""); -> bekerja HostingEnvironment.MapPath (""); -> menimbulkan kesalahan
VSP
14

Saya tidak tahu apakah ini akan menyelesaikan masalah direktori virtual Anda, tetapi saya menggunakan ini untuk MapPath:

public static string MapPath(string path)
{
    if (HttpContext.Current != null)
        return HttpContext.Current.Server.MapPath(path);

    return HttpRuntime.AppDomainAppPath + path.Replace("~", string.Empty).Replace('/', '\\');
}

sumber
path.Replace ("~", string.Empty) harus path.Replace ('~', '.')
Slava
13

HostingEnvironment bukanlah solusi yang tepat karena ini adalah kelas yang sangat sulit untuk diejek (lihat Cara menguji unit kode yang menggunakan HostingEnvironment.MapPath ).

Bagi mereka yang membutuhkan testability, cara yang lebih baik mungkin dengan membuat antarmuka mapper jalur Anda sendiri seperti yang diusulkan oleh https://stackoverflow.com/a/1231962/85196 , kecuali mengimplementasikannya sebagai

public class ServerPathMapper : IPathMapper { 
 public string MapPath(string relativePath) { 
      return HostingEnvironment.MapPath(relativePath); 
 } 
} 

Hasilnya mudah diolok-olok, menggunakan HostingEnvironment secara internal, dan bahkan berpotensi mengatasi masalah ase69s pada saat yang bersamaan.

Mike
sumber
Ini memungkinkan saya untuk menyediakan implementasi resolusi jalur untuk proyek API Web tanpa memerlukan ketergantungan ke System.Web atau System.Net di perpustakaan yang dirujuknya. +1
David Peterson
Jempol untuk DI dan Testabilitas dari pendekatan ini
Dilhan Jayathilake
2

Bisakah Anda tidak memanggil fungsi MapPath sebelum memulai pengatur waktu, dan cukup menyimpan hasilnya dalam cache? Apakah benar-benar perlu memiliki panggilan MapPath di dalam acara tick?

Mark S. Rasmussen
sumber
2

Saat timer berlalu, tidak ada konteks HTTP saat ini. Ini karena peristiwa pengatur waktu tidak terkait dengan permintaan HTTP tertentu.

Yang harus Anda lakukan adalah menggunakan HttpServerUtility.MapPath di mana konteks HTTP tersedia. Anda dapat melakukannya di salah satu acara pipeline permintaan (seperti Page_Load) atau di acara Global.asax seperti Application_Start.

Tetapkan hasil MapPath ke variabel yang dapat diakses dari acara Timer.Elapsed, di mana Anda dapat menggunakan Path.Combine untuk mendapatkan lokasi file tertentu yang Anda butuhkan.

zvikara
sumber
0

Saya pikir alasan mengapa itu nol pada waktu itu (jika Anda memikirkannya), adalah bahwa peristiwa waktu berlalu pengatur waktu tidak terjadi sebagai bagian dari permintaan HTTP (karenanya tidak ada konteks). Ini disebabkan oleh sesuatu di server Anda.

Vaibhav
sumber