When checking in a document I execute a web service within the ItemCheckingInEvent. In Dev, no problems. I deployed the app out and it turns out I don't have enough privileges to read a configuration file. My code reads a config file to create the WCF proxy. The real issue is how can I get a return back from my function if I use the SPSecurity.RunWithElevatedPrivileges function?
For example:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// exec service call
});
// need data from service call here
Just declare your working object before the elevated delegate, and assign it inside:
object myServiceData = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
myServiceData = DoServiceStuff();
});
//do things with myServiceData
Related
How can I access to read/write/modify/delete Playfab data with Azure functions?
Below Steps will help you in accessing the azure functions with Playfab
Create Azure Function in VS Code
Deploy the azure function to portal and register your function with cloud script
Below is the sample example code for calling cloud script using azure functions from your playfab.
//This snippet assumes that your game client is already logged into PlayFab.
using PlayFab;
using PlayFab.CloudScriptModels;
private void CallCSharpExecuteFunction()
{
PlayFabCloudScriptAPI.ExecuteFunction(new ExecuteFunctionRequest()
{
Entity = new PlayFab.CloudScriptModels.EntityKey()
{
Id = PlayFabSettings.staticPlayer.EntityId, //Get this from when you logged in,
Type = PlayFabSettings.staticPlayer.EntityType, //Get this from when you logged in
},
FunctionName = "HelloWorld", //This should be the name of your Azure Function that you created.
FunctionParameter = new Dictionary<string, object>() { { "inputValue", "Test" } }, //This is the data that you would want to pass into your function.
GeneratePlayStreamEvent = false //Set this to true if you would like this call to show up in PlayStream
}, (ExecuteFunctionResult result) =>
{
if (result.FunctionResultTooLarge ?? false)
{
Debug.Log("This can happen if you exceed the limit that can be returned from an Azure Function, See PlayFab Limits Page for details.");
return;
}
Debug.Log($"The {result.FunctionName} function took {result.ExecutionTimeMilliseconds} to complete");
Debug.Log($"Result: {result.FunctionResult.ToString()}");
}, (PlayFabError error) =>
{
Debug.Log($"Opps Something went wrong: {error.GenerateErrorReport()}");
});
}
PlayFab CloudScript Context, Variables and Server SDKs
You will need to install the PlayFab SDK via Package Manager. To do this open Terminal or CMD Console in Visual Studio Code and type: dotnet add package PlayFabAllSDK
We have created some helpers that will ship with the cSharpSDK.
You need to edit your .csproj file and include <DefineConstants>NETCOREAPP2_0</DefineConstants> in your default PropertyGroup or NETCOREAPP3_1 if you are using the latest.
Execution of a script can occur through several methods (APIs, Scheduled Tasks, PlayStream Event, Segment Entering and Exit method). The context of the execution is important to implement your CloudScript. See the Using CloudScript context models tutorial for details on how to use the context of the script.
For further information check Cloud Script Using Azure Functions and Playfab Cloud Script
When creating an instance of a service using TopShelf I'd like to be able to access the service instance name(which may have been set on the command line during installation as a service; which means I don't have direct access to it) to be able to use that as a property for the log file name in Log4Net.
In the example code below we set various properties which are available to use for logging in the global context. I'd love to be able to set the Service instance name here also; but can't seem to be able to get access to it during host initialization.
Anyone any suggestions as to how I could access the service instance name value at run time with Topshelf.
The example below is part of a common function which all our services use to start a service using Topshelf.
public static TopshelfExitCode Run(Func<IConsumerController> controllerFactory,
string serviceName,
string serviceDescription)
{
// Initialise the Global log4net properties so we can use them for log file names and logging when required.
log4net.GlobalContext.Properties["custom-assembly"] = System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location);
log4net.GlobalContext.Properties["custom-processname"] = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
log4net.GlobalContext.Properties["custom-process-id"] = System.Diagnostics.Process.GetCurrentProcess().Id;
// WOULD LIKE ACCESS TO THE SERVICE INSTANCE NAME HERE
var logFileInfo = new System.IO.FileInfo(".\\Log.config");
log4net.Config.XmlConfigurator.Configure(logFileInfo);
var host = HostFactory.New(r =>
{
var controller = controllerFactory();
r.Service<ConsumerService>( () => new ConsumerService(controller));
r.SetServiceName(serviceName);
r.SetDescription(serviceDescription + " © XYZ Ltd. 2012");
r.SetDisplayName(serviceDescription + " © XYZ Ltd. 2012");
r.StartAutomatically();
r.EnablePauseAndContinue();
r.RunAsLocalSystem();
});
return host.Run();
}
The HostSettings are passed to the service factory, which contains the InstanceName as a property. You should use that to initialize the log appender you want to add to log4net.
The instance name is passed on the command line, you can access the command line arguments and pull it from there. This might take a little tweaking, but if you look at the ServiceInstaller you can see how we adjust the command path via registry editing once the service is installed.
I have created a local storage in my web role called "MyTestCache" as so in my
ServiceDefinition.csdef file. But when ever I call the System.IO.File.WriteAllBytes method I get a UnauthorizedAccess exception. Does anyone know what would be causing this? I dont get this when creating the directory in the code below, only when writing. I am using SDK 1.3.
private void SaveFileToLocalStorage(byte[] remoteFile, string filePath)
{
try
{
LocalResource myIO = RoleEnvironment.GetLocalResource("MyTestCache");
// Creates directory if it doesn't exist (ie the first time)
if (!Directory.Exists(myIO.RootPath + "/thumbnails"))
{
Directory.CreateDirectory(myIO.RootPath + "/thumbnails");
}
string PathToFile = Path.Combine(myIO.RootPath + "/thumbnails", filePath);
var path = filePath.Split(Char.Parse("/"));
// Creates the directory for the content item (GUID)
if (!Directory.Exists(Path.Combine(myIO.RootPath + "/thumbnails", path[0])))
{
Directory.CreateDirectory(Path.Combine(myIO.RootPath + "/thumbnails", path[0]));
}
// Writes the file to local storage.
File.WriteAllBytes(PathToFile, remoteFile);
}
catch (Exception ex)
{
// do some exception handling
return;
}
}
Check ACLs. In SDK 1.3 by default web roles are started in full IIS worker process, using Network Service as identity of application pool. Make sure Network Service account has permissions to execute operations you expect. In your case you are trying to create a sub-directory, so most probably you need at least Write permission. If your role also modifies ACLs on this directory, you need to grant Full access to this directory.
Warning: I'm an asp.net developer taking my first steps in SharePoint.
So, i'm writing a console application that connects to a SharePoint Server 2007 site on the same machine, but it seems that something goes wrong during the call to SPSite() constructor. Here's the simplified code:
using (SPSite siteCollection = new SPSite("http://server/AwesomeSite"))
{
//when i set a breakpoint on this line and inspect the siteCollection object,
//most of it's properties (for example siteCollection.AllWebs.Names) throw an
//exception, which leads me to the conclusion that something went wrong during
//the constructor above.
SPWebCollection site = siteCollection.AllWebs;
SPWeb web = site[""];
SPList list = web.Lists["AwesomeList"]; //exception occurs here
}
The SPException text:
Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
I followed the advice of Sharepoint SPSite and checked that:
The user is a server farm administrator.
The user has Read and Write permissions on the content database.
The user is a site collection administrator.
The user has permissions to access the Windows SharePoint Services site or the SharePoint Server 2007 site through which the code iterates.
And they are all correct. What else could be causing this to happen?
In my experience, the SPSite() constructor is highly dependent on the Alternate Access Mappings configuration of your site. Make sure that the URL you are using in the constructor appears in the list of mappings (e.g., http vs. https, machine vs. FQDN).
You need to get more debug information.
Using Visual Studio
Try setting the debugger to break on all exceptions. Go to Debug, Exceptions and tick Common Language Runtime Exceptions. Then go to Tools, Options, Debugging and untick Enable Just My Code. Finally attach to w3wp.exe. Try running your console application now and you should find that it triggers an exception in w3wp.exe. Check the stack trace and see if that gives you more information.
Using dump files
You could also try working from a crash dump. This is admittedly significantly more hard-core but should give you the detail you are otherwise lacking. The tool ProcDump will can be attached to w3wp.exe (provided the -s switch isn't used) and will create a dump if an unhandled exception occurs. If you have trouble with ProcDump, try ADPlus which does something similar.
From the created dump file, use this KB article to set up WinDbg and get started. There is an example case of how to use WinDbg on Tess Ferrandez's blog (Strategy #2).
Have you tried to run the code with elevated privileges?
Does the IIs have some kind of funky settings regarding authentication? (Try Windows auth. only)
Unfortunately, there are hundreds of ways to generate this error. Just ask Google.
You might consider using SPTraceView to get a better description of the error. Here's a description of the tool and an example working an issue with it.
Good luck!
I have similar (not equals) problem. I've solved it with this piece of code:
using( SPSite site = ConnectToSharepointAsSystem() ) {
// now should be all ok
}
// somewhere in helper class ->
public static SPUserToken GetSystemToken(SPSite site) {
SPUserToken token = null;
bool tempCADE = site.CatchAccessDeniedException;
try {
site.CatchAccessDeniedException = false;
token = site.SystemAccount.UserToken;
}
catch (UnauthorizedAccessException) {
SPSecurity.RunWithElevatedPrivileges(() => {
using (SPSite elevSite = new SPSite(site.ID))
token = elevSite.SystemAccount.UserToken;
});
}
finally {
site.CatchAccessDeniedException = tempCADE;
}
return token;
}
public static Microsoft.SharePoint.SPSite ConnectToSharepoint() {
string urlSharepointSite;
var ret = ConnectToSharepoint(out urlSharepointSite);
return ret;
}
public static Microsoft.SharePoint.SPSite ConnectToSharepoint(out string urlSharepointSite) {
urlSharepointSite = "http://www.domain.org";
var site = new Microsoft.SharePoint.SPSite( urlSharepointSite );
return site;
}
public static Microsoft.SharePoint.SPSite ConnectToSharepointAsSystem() {
string urlSharepointSite;
Microsoft.SharePoint.SPUserToken userToken = null;
using (var tmpSite = CSharepointNastroje.PripojitNaSharepoint( out urlSharepointSite )) {
userToken = GetSystemToken(tmpSite);
}
var site = new Microsoft.SharePoint.SPSite(urlSharepointSite, userToken);
return site;
}
This is a question for a WSS/SharePoint guru.
Consider this scenario: I have an ASP.Net web service which links our corporate CRM system and WSS-based intranet together. What I am trying to do is provision a new WSS site collection whenever a new client is added to the CRM system. In order to make this work, I need to programmatically add the managed path to the new site collection. I know that this is possible via the Object Model, but when I try it in my own web service, it fails. Sample code extract below:
Dim _ClientSiteUrl As String = "http://myintranet/clients/sampleclient"
Using _RootWeb As SPSite = New SPSite("http://myintranet")
Dim _ManagedPaths As SPPrefixCollection = _RootWeb.WebApplication.Prefixes
If Not (_ManagedPaths.Contains(_ClientSiteUrl)) Then
_ManagedPaths.Add(_ClientSiteUrl, SPPrefixType.ExplicitInclusion)
End If
End Using
This code fails with a NullReferenceException on SPUtility.ValidateFormDigest(). Research suggested that this may be due to insufficient privileges, I tried running the code within an elevated privileges block using SPSecurity.RunWithElevatedPrivileges(AddressOf AddManagedPath), where AddManagedPath is a Sub procedure containing the above code sample.
This then fails with an InvalidOperationException, "Operation is not valid due to the current state of the object."
Where am I going wrong?
One workaround I have managed to do is to call out to STSADM.EXE via Process.Start(), supplying the requisite parameters, and this works.
Update: whilst developing the web service, I am running it using the built-in Visual Studio 2005 web server - what security context will this be running under? Can I change the security context by putting entries in web.config?
Update: I think the problem is definitely to do with not running the web service within the correct SharePoint security context. I decided to go with the workaround I suggested and shell out to STSADM, although to do this, the application pool identity that the web service runs under must be a member of the SharePoint administrators.
Update
I think you have proved that the issue is not with the code.
SPSecurity.RunWithElevatedPrivileges: Normally the code in the SharePoint web application executes with the privileges of the user taking the action. The RunWithElevatedPrivileges runs the code in the context of the SharePoint web application pools account (i think)
The description on MSDN could go into the details a tiny bit more.
The issue with the call may be that the web service is not actually running the code within a SharePoint process, so explaining why it cannot elevate (wild guess alert).
Have a crack at changing the user of your web services application pool and see if that gives any joy.
It is likely to be a permissions issue.
Maybe try:
Dim clientSiteUrl As String = "http://myintranet/clients/sampleclient"
Using SPSite = new SPSite(clientSiteUrl)
webApp As SPWebApplication = SPWebApplication.Lookup(new Uri(clientSiteUrl));
If Not (webApp.Prefixes.Contains(clientSiteUrl)) Then
webApp.Prefixes.Add(clientSiteUrl, SPPrefixType.ExplicitInclusion)
End If
End Using
This is not exact code.
Since the above code is not the exact code, here is the exact working code for a Web Application scopped feature in the Feature Activated event:
On feature activation at the Mange web application features page, activate feature will create a new Explicit managed path in the specified web application (I want to replace the hard coding, maybe with Properties.Feature.Parent, or something similar.)
using (SPSite site = new SPSite("http://dev-moss07-eric/PathHere")) {
SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://dev-moss07-eric"));
if (webApp.Prefixes.Contains("PathHere"))
{
//
}
else
{
webApp.Prefixes.Add("PathHere", SPPrefixType.ExplicitInclusion);
}
}
Code can probably be improved, but its my attempt at converting the above code.
If you want to create a managed path (explicit) and a site collection at that path, do the following:
using (SPSite site = new SPSite("http://dev-moss07-eric")) {
SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://dev-moss07-eric"));
if (webApp.Prefixes.Contains("ManagedPathHere"))
{
//
}
else
{
webApp.Prefixes.Add("ManagedPathHere", SPPrefixType.ExplicitInclusion);
}
using (SPWeb web = site.OpenWeb())
{
SPWebApplication webApplication = web.Site.WebApplication;
try
{
webApplication.Sites.Add("ManagedPathHere","Site Title Here","This site is used for hosting styling assets.", 1033, "STS#1", "6scdev\\eric.schrader", "Eric Schrader", "eric.schrader#6sc.com");
}
catch (Exception ex)
{
//ex.ToString;
}
}
}