为什么PreApplicationStartMethodAttribute()在SharePoint 2013中不起作用?

时间:2013-01-17 08:19:40

标签: sharepoint routing global-asax sharepoint-2013

在.NET 4(.5)中有这个惊人的AttributePreApplicationStartMethodAttribute, 我想在SharePoint 2013中使用它,因此我不必直接编辑app_start文件中的global.asax方法。

由于SP2013运行的是正确版本的.NET,我认为这个属性可以正常工作......但似乎并非如此。

有没有人想出如何使用它?或解释为什么它不起作用?

小更新: 在system.web dll中,我可以看到下面的类调用了PreApplicationStartMethodAttribute

// System.Web.Compilation.BuildManager
internal static ICollection<MethodInfo> GetPreStartInitMethodsFromAssemblyCollection(IEnumerable<Assembly> assemblies, bool buildingFromCache)
{
    List<MethodInfo> list = new List<MethodInfo>();
    foreach (Assembly current in assemblies)
    {
        PreApplicationStartMethodAttribute[] array = null;
        try
        {
            array = (PreApplicationStartMethodAttribute[])current.GetCustomAttributes(typeof(PreApplicationStartMethodAttribute), true);
        }
        catch
        {
        }
        if (array == null || !array.Any<PreApplicationStartMethodAttribute>())
        {
            if (buildingFromCache)
            {
                return null;
            }
        }
        else
        {
            PreApplicationStartMethodAttribute[] array2 = array;
            for (int i = 0; i < array2.Length; i++)
            {
                PreApplicationStartMethodAttribute preApplicationStartMethodAttribute = array2[i];
                MethodInfo methodInfo = null;
                if (preApplicationStartMethodAttribute.Type != null && !string.IsNullOrEmpty(preApplicationStartMethodAttribute.MethodName) && preApplicationStartMethodAttribute.Type.Assembly == current)
                {
                    methodInfo = BuildManager.FindPreStartInitMethod(preApplicationStartMethodAttribute.Type, preApplicationStartMethodAttribute.MethodName);
                }
                if (!(methodInfo != null))
                {
                    throw new HttpException(SR.GetString("Invalid_PreApplicationStartMethodAttribute_value", new object[]
                    {
                        current.FullName,
                        (preApplicationStartMethodAttribute.Type != null) ? preApplicationStartMethodAttribute.Type.FullName : string.Empty,
                        preApplicationStartMethodAttribute.MethodName
                    }));
                }
                list.Add(methodInfo);
            }
        }
    }
    return list;
}

如果SharePoint 2013在asp.net 4.0上运行,我可能会在应用程序上调用以下内容。

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe

4 个答案:

答案 0 :(得分:2)

以下只是推测,但基于实验。

我认为SharePoint 2013使用某种运行时程序集加载来加载任何和所有自定义代码程序集。毕竟,当我们添加WebPart时,应用程序不会重新编译。这里描述了一种简单的方法:http://msdn.microsoft.com/en-us/library/d133hta4.aspx

我创建了一个简单的ASP MVC应用程序,我尝试了这种精确的技术,并在我的global.asax中加载了一个程序集:

 protected void Application_Start()
    {
        ObjectHandle handle = Activator.CreateInstance("ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=27b9c31f70a4bee3", "ClassLibrary1.Class1");
        Object p = handle.Unwrap();
        Type t = p.GetType();

        MethodInfo method = t.GetMethod("ToString");
        Object retVal = method.Invoke(p, null);
    }

正在加载的程序集是我创建并放置在GAC中的内容。这个ClassLibrary1实际上是准系统,类Class1包含一个方法ToString()。 ToString方法抛出异常,如果被调用则很容易看到:

public class Class1
{
    public override string ToString()
    {
        throw new ApplicationException("Joe was in the tostring");
        return base.ToString();
    }
}

程序集还使用AssemblyInfo.cs文件中的PreApplicationStartMethod:

[assembly: PreApplicationStartMethod(typeof(ClassLibrary1.JoeAssemblyStart), "Start")]

最后,PreApplicationStartMethod属性调用了一个简单的类:

 public class JoeAssemblyStart
{
    public static void Start()
    {
        throw new ApplicationException("joe was here in this assembly start");
    }
}

有趣的事情发生在运行时。当我运行此代码时,抛出的异常来自Class1中的ToString,而不是JoeAssemblyStart类。这意味着在运行时加载程序集时会忽略PreApplicationStartMethod属性,这在考虑ASP.NET管道时就不足为奇了。

当我将ClassLibrary1明确地添加到我的MVC项目并且没有动态加载它时,我也运行了这个实验的一个版本。在这种情况下,PreApplicationStartMethod代码按预期调用。

总结一下:

  1. 向您添加代码时不会重建SharePoint 2013
  2. 因此,您的代码必须以某种动态方式加载
  3. 动态加载的程序集早在PreApplicationStartMethod
  4. 时就不会影响ASP.NET管道

答案 1 :(得分:2)

这有点晚,但我认为这很重要。

PreApplicationStartMethod属性在SharePoint 2013中运行正常。但是,需要将程序集部署到bin文件夹。

步骤

  1. 创建常规SharePoint解决方案(将其称为SharePointProject)。
  2. 创建一个新的类库项目并为其指定一个强名称。 (我们称之为ClassProject)
  3. 将名为Startup的新类添加到ClassProject。
  4. 添加一个名为Start to Startup的静态方法并执行启动工作。
  5. 将PreApplicationStartMethod指向ClassProject的Startup属性。
  6. 转到SharePointProject中的打包/高级设置,并将ClassProject添加为需要部署的程序集。确保选择WebApplication而不是gac。
  7. 部署您的解决方案。
  8. 此过程会将ClassProject部署到SharePoint Web应用程序的bin文件夹中。 start方法将由运行时调用,一切都应该有效。确保将ClassProject部署到WebApplication而不是GAC非常重要。

    如果你已经玩了一段时间而且它不起作用。尝试删除Internet临时文件下的所有内容,因为IIS喜欢缓存Dll,并且不会调用您的代码。

    哦,使用ClassProject的原因是因为如果将SharePoint项目部署到bin而不是GAC,则无法使用Feature Receivers。

答案 2 :(得分:1)

我注意到一些项目没有“PreApplicationStartup”我在控制台应用程序上遇到了类似的问题,尽管它在网站上运行良好。

也可能是您运行的方法不是静态方法。

public class PreApplicationStart
    {
        public static void Start()
        {
            // Pre application startup configuration goes here
        }
    }

在AssemblyInfo.cs中添加以下内容

[assembly: PreApplicationStartMethod(typeof(PreApplicationStart), "Start")]

答案 3 :(得分:1)

我尝试了几种方法 - 我使用它的唯一方法是使用httpmodule:http://melcher.it/2012/12/signalr-in-sharepoint-2013-the-real-time-web-is-coming/

我认为PreApplicationStart不起作用的原因是因为global.asax继承了SPHttpApplication而不是HttpApplication - 没时间浏览源代码。

这么久, 最大