This guide explains the steps to create a winforms database first application
http://codehelper.net/entity-framework/winforms-net-core-tips/
This guide explains the steps to create a winforms database first application
http://codehelper.net/entity-framework/winforms-net-core-tips/
It is important to configure certificates correctly for a provider hosted app in SharePoint website since the authentication requires communication between Azure AD, SharePoint, and our app, which is hosted on a different IIS server.
I have added this method to TokenHelper class and call it in CSOM webpart methods to trust certificates
public class TokenHelper
{
#region public methods
/// <summary>
/// Configures .Net to trust all certificates when making network
calls. This is used so that calls
/// to an https SharePoint server without a valid certificate are not
rejected. This should only be used
during
/// testing, and should never be used
in a production app.
/// </summary>
public static void TrustAllCertificates()
{
//Trust
all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate,
chain, sslPolicyErrors) => true);
}
}
Also there are some articles which describe certificates trust configuration on a sharepoint farm
https://docs.microsoft.com/en-us/sharepoint/administration/exchange-trust-certificates-between-farms
https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/create-high-trust-sharepoint-add-ins
This one liner can return absolute url of an item using its FileRef property
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>
}
If we get this error while trying to get http reponse using HttpClient object, it could mean that certificate validation fails for the remo...