获取要在asp.net Web应用程序中读取的文本文件的完整路径

时间:2015-01-11 20:41:50

标签: c# asp.net

这是一个非常恼人的问题,我在堆栈和谷歌上进行了数十次搜索后无法解决这个问题。

我有一个Asp.Net Web应用程序,该解决方案本身有7个项目,其中一个是MVC项目,其中有如下所示的类。

using System;
using System.Web.Hosting;
namespace MyApp.Notifications
{
    public class CustomEmails
    {
        private readonly string basePath = "C:\\Users\\MyUser\\MyAppName\\";
        //HostingEnvironment.MapPath("~\\MyAppName")
        //Server.MapPath("~")
        //HostingEnvironment.ApplicationPhysicalPath("~");
       //HostingEnvironment.ApplicationVirtualPath;

       var subject = File.ReadAllText(basePath + "Notifications\\EmailTemplates\\EmailConfirmationEvent_Subject.txt");
  //rest of classes code here
    }
}

我可以在子文件夹中读取文本文件的唯一方法是对路径进行硬编码,如上所示。如您所见,我试图以编程方式检索应用程序的基本路径,然后将其添加到文件子路径中。

正如您在上面所看到的那样,在已注释的片段中,我尝试过很多事情。

对于初学者来说,永远不允许使用Server.MapPath,因为它始终是红色的,intellisense没有提供任何补救措施,谷歌搜索也没有提供太多其他服务,因为Server.MapPath是一种IIS方法。所有其他代码片段都没有返回任何内容。

我做错了什么?错误在哪里?是不是有一种标准的方式,所以无论是在开发机器上还是在主机虚拟机上,总是能获得正确的基本路径?

Per Darin的建议代码更新如下;

 public class EmailEvents
{
   private static readonly string basePath = CustomEmails.GetWebsiteRoot();
   public class EmailAddressVerified : IEventHandler<EmailVerifiedEvent<UserAccount>>
    {
        public void Handle(EmailVerifiedEvent<UserAccount> evt)
        {
            dynamic smtp = new SmtpMessageDelivery();
            var localAppPath =  CustomEmails.GetWebsiteRoot();
            var htmlBody = CustomEmails.GetHtmlEmailMessage(DomainClasses.Enums.EmailType.AccountConfirmation);
            //{ProductionChange} --change the first parameter to false in production
            htmlBody = CustomEmails.FillEmailPlaceholderText(false, htmlBody, evt.Account);
            htmlBody = htmlBody.Replace(CustomEmails.EmailTextPlaceholders.HtmlFileKey, EncryptDecrypt.EncryptQueryString(Guid.NewGuid().ToString()));              
            var subject = File.ReadAllText(Path.Combine(basePath, "Notifications", "EmailTemplates", "EmailConfirmationEvent_Subject.txt"));
            subject = subject.Replace(CustomEmails.EmailTextPlaceholders.ApplicationName, CustomEmails.EmailPlaceholderValues.ApplicationName);

            var msg = new Message { To = evt.Account.Email, Subject = subject, Body = htmlBody };
            smtp.Send(msg);
        }
    }
}

在上面的示例中,basePath始终没有,但localAppPath检索正确的路径。为什么类级私有变量不能检索路径?

2 个答案:

答案 0 :(得分:0)

您可以声明一个变量,然后稍后在运行时填充该变量,只使用get使其成为只读,然后在属性中使用Server.MapPath。您不能像在类声明中那样在编译时执行此操作,因为它无法解决字符串const的问题,因为Server.MapPath无法解析为它可以使用的const,因为它几乎肯定会改变部署。

public class CustomEmails
{
    private string _basePath = null;

    private string BasePath 
    {
        get 
        {
             if ( _basePath == null ) 
             {
                 this._basePath = Server.MapPath('...');  
             }
             return _basePath;
        }
    }

在运行时,您对this.BasePath的第一个请求将使用MapPath(一次调用)填充私有变量,然后对该方法的所有后续调用将使用先前获取的值。

答案 1 :(得分:0)

您可以使用HostingEnvironment.MapPath静态方法。

  1. 添加对System.Web程序集
  2. 的引用
  3. 添加using System.Web.Hosting
  4. 使用指向网站根目录的单一方法编写一个类:

    using System.Web.Hosting;
    
     namespace MyApp.Notifications
     {
         public class CustomEmails
         {
             public static string GetWebsiteRoot()
             {
                 // Get the website root
                 return HostingEnvironment.MapPath("~/");
             }
         }
     }
    
  5. 备注:HostingEnvironment.MapPath仅适用于ASP.NET虚拟主机。如果您尝试在外部使用它(例如单元测试或桌面应用程序),它将不会返回所需的结果。

    在这种情况下,让您的函数作为网站根路径的依赖关系会好得多。这将使它们更容易进行单元测试。只有在Composition Root中,您才会使用正确的方法来注入路径。对于可以是HostingEnvironment.MapPath方法的ASP.NET Web上下文。

    此外,当您处理目录路径时,您完全想要使用Path.Combine方法而不是您在问题中使用的+运算符。例如:

    string root = CustomEmails.GetWebsiteRoot();
    string path = Path.Combine(root, "Notifications", "EmailTemplates", "EmailConfirmationEvent_Subject.txt");