Wednesday, February 23, 2022

SharePoint add in part - postback error localhost refused to connect

 While developing an addin part using CSOM I was able to use a button to postback the data, but the addin part would show the error 'Localhost refused to connect'. So I was trying to find out why the addin part work on initial load but fails to load when postback method return the view.

After investingating the forms collection I noticed that there are some tokens added to the forms collection by sharepoint in the inital part load request. These tokens are used by IIS to validate the user request, thus they need to be sent with every request. The code below solved this issue:


In the controller I added the method CopyTokens

    private void CopyTokens(AddInViewmodel viewModel)

        {

            if (Request.Form["SPAppToken"] != null)

            {

                viewModel.SPAppToken = Request.Form["SPAppToken"];

            }

            if (Request.Form["SPSiteUrl"] != null)

            {

                viewModel.SPSiteUrl = Request.Form["SPSiteUrl"];

            }

            if (Request.Form["SPSiteTitle"] != null)

            {

                viewModel.SPSiteTitle = Request.Form["SPSiteTitle"];

            }

            if (Request.Form["SPSiteLogoUrl"] != null)

            {

                viewModel.SPSiteLogoUrl = Request.Form["SPSiteLogoUrl"];

            }

            if (Request.Form["SPSiteLanguage"] != null)

            {

                viewModel.SPSiteLanguage = Request.Form["SPSiteLanguage"];

            }

            if (Request.Form["SPSiteCulture"] != null)

            {

                viewModel.SPSiteCulture = Request.Form["SPSiteCulture"];

            }

            if (Request.Form["SPRedirectMessage"] != null)

            {

                viewModel.SPRedirectMessage = Request.Form["SPRedirectMessage"];

            }

            if (Request.Form["SPCorrelationId"] != null)

            {

                viewModel.SPCorrelationId = Request.Form["SPCorrelationId"];

            }

            if (Request.Form["SPErrorCorrelationId"] != null)

            {

                viewModel.SPErrorCorrelationId = Request.Form["SPErrorCorrelationId"];

            }

            if (Request.Form["SPErrorInfo"] != null)

            {

                viewModel.SPErrorInfo = Request.Form["SPErrorInfo"];

            }

        }

I called this method just before completing the postback handler

            public ActionResult Index()

        {

            var viewModel = new AddInViewmodel();

           

            TokenHelper.TrustAllCertificates();

            string contextTokenString = TokenHelper.GetContextTokenFromRequest(Request);

 

            if (contextTokenString != null)

            {

                // Get context token

                var contextToken = TokenHelper.ReadAndValidateContextToken(contextTokenString, Request.Url.Authority);

 

                // Get access token

                Uri sharepointUrl = null;

                if (Request.QueryString["SPAppWebUrl"] != null)

                {

                    sharepointUrl = new Uri(Request.QueryString["SPAppWebUrl"]);

                    var accessToken = TokenHelper.GetAccessToken(contextToken, sharepointUrl.Authority).AccessToken;

                }

               

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

                if (spContext != null)

                {

                    using (var clientContext = spContext.CreateUserClientContextForSPHost())

                    {

                        if (clientContext != null)

                        {

                            // Code to fetch data from SharePoint site into view model

 

                        }

                    }

                }

            }

            CopyTokens(viewModel);

 

            return View(viewModel);

        }

Lastly, I have added some hidden controls in the view to persist and send these tokens in each new postback request, also note the querystring parameters added to reqeust.


@using (Html.BeginForm(actionName: "Index", controllerName: "MyAddInWebpart",

    routeValues: new

    {

        SPHostUrl = Request.QueryString["SPHostUrl"],

        SPHostTitle = Request.QueryString["SPHostTitle"],

        SPAppWebUrl = Request.QueryString["SPAppWebUrl"],

        SPLanguage = Request.QueryString["SPLanguage"],

        SPClientTag = Request.QueryString["SPClientTag"],

        SPProductNumber = Request.QueryString["SPProductNumber"],

        SenderId = Request.QueryString["SenderId"]

    }, method: FormMethod.Post, htmlAttributes: new { }))

    {

        @*@Html.AntiForgeryToken()*@

        @Html.HiddenFor(model => model.SPAppToken)

        @Html.HiddenFor(model => model.SPSiteUrl)

        @Html.HiddenFor(model => model.SPSiteTitle)

        @Html.HiddenFor(model => model.SPSiteLogoUrl)

        @Html.HiddenFor(model => model.SPSiteLanguage)

        @Html.HiddenFor(model => model.SPSiteCulture)

        @Html.HiddenFor(model => model.SPRedirectMessage)

        @Html.HiddenFor(model => model.SPCorrelationId)

        @Html.HiddenFor(model => model.SPErrorCorrelationId)

        @Html.HiddenFor(model => model.SPErrorInfo)

<div class="form"><div class="form-group"><div class="form-row">

       <input type="submit" class="btn btn-default" value="Save" />

</div></div></div>

}


1 comment:

wahidahgahn said...

Casinos near casino near me - Mapyro
Find the closest casino to me in 경주 출장안마 Murphy in 안성 출장샵 Murphy. Mapyro provides accurate local and international gambling information to 대구광역 출장샵 help 안산 출장샵 you choose ‎Casinos Near Murphy 포항 출장마사지 · ‎Harrah's Casino Murphy

c# httpclient The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch

 If we get this error while trying to get http reponse using HttpClient object, it could mean that certificate validation fails for the remo...