簡體   English   中英

如何在不使用查詢字符串的情況下移動ASP.NET MVC應用程序時保留Sharepoint上下文?

[英]How do i keep the Sharepoint context when moving around an ASP.NET MVC application without using the query string?

我正在MVC 4.5中構建一個小應用程序。 我有一個Azure數據庫,我首先使用代碼框架來設置代碼。 該應用程序托管在我的開發sharepoint區域。

Home控制器的Index() Action具有[SharePointContextFilter]並加載了登錄用戶的用戶名等。 調試應用程序並運行第一個操作時,Sharepoint {StandardTokens}將附加到url,因此SPHostUrlAppWebUrl以及一些其他變量將添加到查詢字符串中。

如果我導航到沒有[SharePointContextFilter]它可以正常工作,直到我使用 [SharePointContextFilter]導航回操作。 然后我得到一個錯誤說:

Unknown User
Unable to determine your identity. Please try again by launching the app installed on your site.

我假設這是因為缺少一些Sharepoint {StandardTokens} ,因為如果我手動將它們附加到鏈接上,如下所示:

@Url.Action("Index", "Home", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Current.Request).AbsoluteUri })

並使用[SharePointContextFilter]標記其他操作,它仍然有效。

Hovever這似乎是解決這個問題的一種不必要的復雜方法。 我不希望使用[SharePointContextFilter]在我的應用中標記每個操作,並手動將{StandardTokens}插入到我創建的每個鏈接的查詢字符串中。 不應該以某種方式將此信息保存到會話或cookie中,所以我不必這樣做嗎?

供參考,這里有一些代碼:

HomeController.Index(),第一個運行的Action。

    [SharePointContextFilter]
    public ActionResult Index()
    {
        User spUser = null;

        var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

        using (var clientContext = spContext.CreateUserClientContextForSPHost())
        {
            if (clientContext != null)
            {
                spUser = clientContext.Web.CurrentUser;

                clientContext.Load(spUser, user => user.Title);

                clientContext.ExecuteQuery();

                ViewBag.UserName = spUser.Title;
            }
        }

        return View();
    }

這是[SharePointContextFilter]屬性(由visual studio生成):

/// <summary>
/// SharePoint action filter attribute.
/// </summary>
public class SharePointContextFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        SharePointContext currentContext = SharePointContextProvider.Current.GetSharePointContext(filterContext.HttpContext);

        Uri redirectUrl;
        switch (SharePointContextProvider.CheckRedirectionStatus(filterContext.HttpContext, out redirectUrl))
        {
            case RedirectionStatus.Ok:
                return;
            case RedirectionStatus.ShouldRedirect:
                filterContext.Result = new RedirectResult(redirectUrl.AbsoluteUri);
                break;
            case RedirectionStatus.CanNotRedirect:
                filterContext.Result = new ViewResult { ViewName = "Error" };
                break;
        }
    }
}

我使用的鏈接。 來自_Layout.cshtml文件:

<li id="Home"><a href="@Url.Action("Index", "Home", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Current.Request).AbsoluteUri })">Home</a></li>
<li id="Contract"><a href="@Url.Action("Index", "Contract", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Current.Request).AbsoluteUri })">Avrop</a></li>

如果我嘗試使用使用[SharePointContextFilter]過濾器標記的操作中的這些鏈接,則SPHostUrl 如果我嘗試連接到有一個動作[SharePointContextFilter]過濾器,我得到上述錯誤,如果SPHostUrl不包括在內。

這基本上創造了一種情況,我可以遠離過濾的動作,但我永遠不會回到它們。

我希望這很清楚。

我們遇到了同樣的問題 - ASP.NET MVC 4.5。 有兩件事對我們有用:

1)有一個spcontext.js文件(包含在解決方案中 - 你只需要添加對它的引用),它會自動將令牌附加到URL。 但是,我們被要求URL必須看起來“不錯”,所以我們選擇了2 ..

2)將上下文放在會話中。 讓過濾器首先查看您的會話中是否有上下文,如果它在那里,那么使用它。 如果沒有,請嘗試查詢字符串並將檢索到的上下文放在會話中。 這意味着您最初必須使用附加到您的網址字符串的令牌訪問您的網站,這也意味着您的上下文將在會話中持續很長時間 - 所以您必須決定是否可以。

另一種選擇是在下面顯示的兩個位置注釋掉SharePointContext類中SPHostUrl的驗證。 它沒有它工作正常,並且無需傳遞QueryString參數,因為它只是將它從Session狀態拉出來。

位置1在公共SharePointContext GetSharePointContext(HttpContextBase httpContext)中

    /// <summary>
    /// Gets a SharePointContext instance associated with the specified HTTP context.
    /// </summary>
    /// <param name="httpContext">The HTTP context.</param>
    /// <returns>The SharePointContext instance. Returns <c>null</c> if not found and a new instance can't be created.</returns>
    public SharePointContext GetSharePointContext(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }

        // Commented out to allow it to work without the SPHostUrl being passed around
        //Uri spHostUrl = SharePointContext.GetSPHostUrl(httpContext.Request);
        //if (spHostUrl == null)
        //{
        //    return null;
        //}

        SharePointContext spContext = LoadSharePointContext(httpContext);

        if (spContext == null || !ValidateSharePointContext(spContext, httpContext))
        {
            spContext = CreateSharePointContext(httpContext.Request);

            if (spContext != null)
            {
                SaveSharePointContext(spContext, httpContext);
            }
        }

        return spContext;
    }

位置2位於受保護的覆蓋bool ValidateSharePointContext(SharePointContext spContext,HttpContextBase httpContext)

    protected override bool ValidateSharePointContext(SharePointContext spContext, HttpContextBase httpContext)
    {
        SharePointAcsContext spAcsContext = spContext as SharePointAcsContext;

        if (spAcsContext != null)
        {
            // Commented out to allow it to work without the SPHostUrl being passed around
            //Uri spHostUrl = SharePointContext.GetSPHostUrl(httpContext.Request);
            string contextToken = TokenHelper.GetContextTokenFromRequest(httpContext.Request);
            HttpCookie spCacheKeyCookie = httpContext.Request.Cookies[SPCacheKeyKey];
            string spCacheKey = spCacheKeyCookie != null ? spCacheKeyCookie.Value : null;

            // Commented out to allow it to work without the SPHostUrl being passed around
            //return spHostUrl == spAcsContext.SPHostUrl &&
            return !string.IsNullOrEmpty(spAcsContext.CacheKey) &&
                   spCacheKey == spAcsContext.CacheKey &&
                   !string.IsNullOrEmpty(spAcsContext.ContextToken) &&
                   (string.IsNullOrEmpty(contextToken) || contextToken == spAcsContext.ContextToken);
        }

        return false;
    }

確保將通過HTTP Post中的SPAppToken變量接收初始請求的應用程序的登錄頁面調用SharePointContext,以便創建會話變量。 這可以通過在MVC Controller類之上或MVC Action方法之上添加以下屬性來完成:

[SharePointContextFilter]

或者從MVC控制器調用以下代碼行:

SharePointContextProvider.Current.GetSharePointContext(HttpContext);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM