How To Get Unique Users In Application Insights Monitoring SharePoint Sites? - sharepoint

We are monitoring SharePoint Online and SharePoint On-Premises sites using Application Insights. We can see in Metrics that there is a report showing Unique users. But the data is anonymised coming from SharePoint Online (i.e. the user_Id is not visible). So these are hits rather than unique users.
How do we surface unique users from recorded data in Application Insights coming from SharePoint Online and SharePoint On-premises monitored sites?

Make sure firstly the UserId is being captured, can you try to embed the below script in the SharePoint app instead of the snippet you get from the portal.
<SharePoint:ScriptLink ID="ScriptLink1" name="SP.js" runat="server" localizable="false" loadafterui="true" />
<SharePoint:ScriptLink ID="ScriptLink2" name="SP.UserProfiles.js" runat="server" localizable="false" loadafterui="true" />
<script type="text/javascript">
var personProperties;
// Ensure that the SP.UserProfiles.js file is loaded before the custom code runs.
SP.SOD.executeOrDelayUntilScriptLoaded(getUserProperties, 'SP.UserProfiles.js');
function getUserProperties() {
// Get the current client context and PeopleManager instance.
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
// Get user properties for the target user.
// To get the PersonProperties object for the current user, use the
// getMyProperties method.
personProperties = peopleManager.getMyProperties();
// Load the PersonProperties object and send the request.
clientContext.load(personProperties);
clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
}
// This function runs if the executeQueryAsync call succeeds.
function onRequestSuccess() {
var appInsights=window.appInsights||function(config){
function s(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},r=document,f=window,e="script",o=r.createElement(e),i,u;for(o.src=config.url||"//az416426.vo.msecnd.net/scripts/a/ai.0.js",r.getElementsByTagName(e)[0].parentNode.appendChild(o),t.cookie=r.cookie,t.queue=[],i=["Event","Exception","Metric","PageView","Trace"];i.length;)s("track"+i.pop());return config.disableExceptionTracking||(i="onerror",s("_"+i),u=f[i],f[i]=function(config,r,f,e,o){var s=u&&u(config,r,f,e,o);return s!==!0&&t["_"+i](config,r,f,e,o),s}),t
}({
instrumentationKey:"XXXX"
});
window.appInsights=appInsights;
appInsights.trackPageView(document.title,window.location.href, {User: personProperties.get_displayName()});
}
// This function runs if the executeQueryAsync call fails.
function onRequestFail(sender, args) {
}
</script>
For additional details please refer to the documentation.
Hope the information helps.

Related

ASP.NET Identity using Azure Active Directory... when/how are AspNetUsers db records created

I have a simple MVC .Core 6 web application that will be used on the corporate extranet (via an azure app service).
I've setup Microsoft Identity for login/authentication. This works really well. User requests a page and they're sent off to the corporate azure active directory login page (include 2fa) and returned to the application authenticated with user claims.
BUT... my Identity database tables remain empty (AspNetUsers et al). I was half expecting a record to be created representing the user that just signed in.
I scaffolded the ExternalLogin.cshtml page expecting it to be displayed after a user logs in (and there I could manually create the user if userManager.GetUserAsync(User) == null). But the page is never shown
I think I want AspNetUsers table entries because my simple app does a bit of audit trail stuff (CreatedByUserId, LastUpdatedByUserId) and I would like these to be foreign keys to the AspNetUsers table.
Thoughts? Are my expectations out of whack?
I was way off base on this.
Microsoft.Identity.Web and Microsoft.Identity.Web.UI don't need/create AspNetUsers table (et al).
If you want to build your own users table when a user logs in to the application you can do the following:
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, opts =>
{
opts.Events = new OpenIdConnectEvents()
{
OnTicketReceived = async (context) =>
{
//
// Pull out the user details
//
var objectidentifier = context.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
var nameidentifier = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var name = context.Principal.FindFirstValue("name");
var email = context.Principal.FindFirstValue("preferred_username");
//
// Demo code to create a record in a users db table
//
using var scope = context.HttpContext.RequestServices.CreateScope();
var ctx = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
var isUserExists = await ctx.MyApplicationUser.AnyAsync(u => u.ObjectIdentifier == objectidentifier);
if (!isUserExists)
{
var applicationUser = new MyApplicationUser()
{
ObjectIdentifier = objectidentifier,
NameIdentifier = nameidentifier,
Email = email,
Name = name,
};
ctx.MyApplicationUser.Add(applicationUser);
await ctx.SaveChangesAsync();
};
}
};
});
Note that some care is needed to pull out the correct claims.
Note this should probably update an existing user if their details changed (names do change).
This is slightly modified from what I found at: https://dotnetthoughts.net/azure-active-directory-b2c-in-aspnet-core-mvc-part1/

How to call restful service in Sharepoint 2013

This is my sharepoint service code to get list of my documents.
var docuList;
function getList(){
var context = new SP.ClientContext('/');
var oColl = context.get_web().get_lists().getByTitle('Test');
var Query = new SP.CamlQuery();
Query.set_viewXml("<View><Query><OrderBy><FieldRef Name=\"Created\" Ascending=\"FALSE\" /></OrderBy></Query><ViewFields><FieldRef Name=\"FileLeafRef\" /><FieldRef Name=\"FileRef\" /></ViewFields></View>");
docuList = oColl.getItems(Query);
context.load(docuList);
context.executeQueryAsync(successCall, failCall);
}
function successCall(res,arg){
var litToIter = docuList.getEnumerator();
while (litToIter.moveNext()) {
var item = litToIter.get_current();
var DocUrl = item.get_item("FileRef");
console.log(DocUrl); // My list of documents which I added
}
}
When I execute this code I am getting my list. But If I use rest service to get a list, am not getting my list of data(Getting some different data in XMl format). I tried Rest call in postman. This is my Restful service URL to get list of documents.
http://MysiteURL/site/_api/lists/getbytitle('Test')
Am not sure whether this is a correct way to hit share point, can someone correct my URL or guide me how to get my list by Rest service.
Thanks.
This REST request will get you all lists available in your site.
http://myserver/_vti_bin/ListData.svc
for more information about calling SharePoint RESTful service, please refer to this MSDN article

Where does TrackRequest() data show up in the portal?

I have a console application logging to TrackRequest in a TelemetryClient, but I can't figure out what tile to display in the Azure portal to see the data.
Is there some guidance that lists each method, the data, and what tile exposes it?
With the following code in a console app:
TelemetryClient client = new TelemetryClient(new TelemetryConfiguration()
{
InstrumentationKey = "<your ikey>",
TelemetryChannel = new InMemoryChannel()
});
client.TrackRequest("Hello", DateTimeOffset.Now, TimeSpan.FromSeconds(1), "200", true);
Console.ReadLine();
Request data will appear on main overview page and in search results.

How to set the security token in breeze to access SharePoint list?

I have used http://www.andrewconnell.com/blog/getting-breezejs-to-work-with-the-sharepoint-2013-rest-api
code in a empty web application project. How can I set the security access in order to deal with the SharePoint list.
function configureBreeze() {
// configure breeze to use SharePoint OData service
var dsAdapter = breeze.config.initializeAdapterInstance('dataService', 'SharePointOData', true);
dsAdapter.defaultSettings = {
xhrFields: {
withCredentials: true
}
};
// tell breeze how to get the security validation token for
// HTTP POST & DELETE calls
dsAdapter.getRequestDigest = function () {
return jQuery('#__REQUESTDIGEST').val();
};
}
I am getting a Access Denied error!
Did you look at all three parts of Andrew's post?
Part 3 talks about security ... the "request digest" in particular ... and shows you how to get the SharePoint OData adapter and set the adapter.getRequestDigest function.
You might want to post additional questions to that blog post too.

How to upload a document to SharePoint programmatically?

I want to upload documents from a web portal to SharePoint programmatically. That is, as user uploads a document it should go directly into SharePoint. I am new to SharePoint and am looking for suggestions/ideas on how to achieve above. Thanks
You have multiple ways of uploading a document, depending on where you code is running. The steps are practically the same.
From the Server Object Model
Use this one if you are working in the SharePoint server side (Web Parts, Event Receivers, Application Pages, etc.)
// Get the context
var context = SPContext.Current;
// Get the web reference
var web = context.Web;
// Get the library reference
var docLib = web.Lists.TryGetList("NAME OF THE LIBRARY HERE");
if (docLib == null)
{
return;
}
// Add the document. Y asume you have the FileStream somewhere
docLib.RootFolder.Files.Add(docLib.RootFolder.Url + "FILE NAME HERE", someFileStream);
From client side code (C#)
Use this one if you are working from a client application that consumes SharePoint services.
// Get the SharePoint context
ClientContext context = new ClientContext("URL OF THE SHAREPOINT SITE");
// Open the web
var web = context.Web;
// Create the new file
var newFile = new FileCreationInformation();
newFile.Content = System.IO.File.ReadAllBytes("PATH TO YOUR FILE");
newFile.Url = "NAME OF THE NEW FILE";
// Get a reference to the document library
var docs = web.Lists.GetByTitle("NAME OF THE LIBRARY");
var uploadFile = docs.RootFolder.Files.Add(newFile);
// Upload the document
context.Load(uploadFile);
context.ExecuteQuery();
From JS using the SharePoint web services
Use this one if you want to upload a document from pages without the server roundtrip:
// Get the SharePoint current Context
clientContext = new SP.ClientContext.get_current();
// Get the web reference
spWeb = clientContext.get_web();
// Get the target list
spList = spWeb.get_lists().getByTitle("NAME OF THE LIST HERE");
fileCreateInfo = new SP.FileCreationInformation();
// The title of the document
fileCreateInfo.set_url("my new file.txt");
// You should populate the content after this
fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
// Add the document to the root folder of the list
this.newFile = spList.get_rootFolder().get_files().add(fileCreateInfo);
// Load the query to the context and execute it (successHandler and errorHandler handle result)
clientContext.load(this.newFile);
clientContext.executeQueryAsync(
Function.createDelegate(this, successHandler),
Function.createDelegate(this, errorHandler)
);
Hope it helps!

Resources