Using Realm Sync with Azure Functions - c#

I'm trying to use Realm Cloud in an Azure Function but it keeps giving me an error:
make_dir() failed: Permission denied Path: /realm-object-server/
Is there a way to configure Azure Functions to have permissions to create files? I'm new to Azure Functions, this is my first one so I'm not really sure of all the particulars.

I have found one solution to this. Inside Azure function, you can only create any file or folder inside the temp folder. So if you use following sync configuration, it should work. It worked for me.
var configuration = new FullSyncConfiguration(new Uri("/~/<your-realm-name>", UriKind.Relative), _realmUser, Path.Combine(Path.GetTempPath(), "realm-object-server"));
So basically, here you are passing the folder name to store the realm locally. If you don't pass the folder name, it will try to store it in a default location where you will get the access error.

I am not familiar with Realm, but functions has permissions to interact with the file system by default. See these links for information on the app service file system (this applies for functions too):
https://learn.microsoft.com/en-us/azure/app-service/operating-system-functionality#file-access
https://github.com/projectkudu/kudu/wiki/Understanding-the-Azure-App-Service-file-system
If the function is deployed using run from package, then the wwwroot is readonly. But since the path in the error message doesn't point to wwwroot, this is probably not the issue.
My best guess is that the code that is failing is trying to write to in an inappropriate location. The information in the links above should help resolve that. Maybe check to see if realm has a config setting that lets you specify which location it should be creating "realm-object-server" in.

You can use
SyncConfigurationBase.Initialize(UserPersistenceMode.NotEncrypted, basePath: Path.GetTempPath());

Related

Azure function app wwwroot folder missing

I have an Azure Function app which is constantly returning 404 for all of the endpoints. The API configuration seems correct so the issue is with the function itself. It had been working fine until recently. The only thing that I have noticed which is strange is that when I compare the folder structure using Kudu, a working function app has a /home/site/wwwroot directory,
but my broken function app does not:
I think this has something to with my issue. I tried to manually create the folder and I get a 409 error.
The code is written in C# and deployments don't work using the azure pipeline as well as manually doing a deployment with
func azure functionapp publish <function app name> --dotnet
I noticed that the app setting WEBSITE_CONTENTSHARE was set to a value that was originally only on the staging slot, something like staging-asdf-fdsa, could that have caused the problem? I tried changing the value and restarted the function app but it didn't seem to make a difference
Does it seem like I am on the right path? Does anyone know why this folder would be gone? I'm wondering if an app setting that I had might have broken my function app when I was doing a swap between my staging slot and production slot.
If there's any additional info that would help please let me know and I will edit this question with it.
UPDATE
I was able to get it to properly create the wwwroot directory by toggling the WEBSITE_RUN_FROM_PACKAGE from 1 to 0, when I did my deployment, it switched it back to 1 and created the wwwroot directory.
The issue is that I still receive a 404 for a valid URL.
Found the root cause. I looked into the C# application that is running and I found that in Startup.cs, the api route suffix was being set. MS documentation is very confusing around this and the intention seems to have been to switch from /api to /api/<something>, and while it appears that worked for the function itself internally, the azure function app was not aware of this change in route, so it kept trying to serve the request at /api. removing this line fixed the issue. I believe that the likely solution in the end if we want to change the route suffix is to update both host.json and the value in Startup.cs, but that's another issue for another SO ticket (hopefully not)

Better solution to store data for dll assembly

I'm developing a dll that is supposed to be commonly used (in nuget for example). Simple description: my DLL simplifies message exchange with a particular service. It allows to send a request, then retrieve a response. Service is asynchronous and it can create a response in a hour or a day after accepting a request, so after making a request my dll calls service every few minutes to check out for response. The problem is that the app that uses the dll can be restarted therefore storing a request queue in memory isn't a good option (I don't want to lose info about requests). Neither is serializing it to file, because I can't know for sure where my dll will be used - it could be pc app, mvc. My main options is: serialize to file, but give an option to set a address where to place serialized files via web/app.config or make a user to think about it. But maybe there is some better solution about how to store requests queue?
I would put theses type of configuration or data files in a subfolder to the %appdata% folder. You will have write access to files in this folder and the documentation is extensive. Read more here.
in C# you can easily get this folder using:
var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
Or use Program Data:
var programdata = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

Delete and upload files into Azure webapp local storage programatically

I've deployed a website into Azure and i want to access programaticaly this path : "D:\home\site\app" from a c# desktop application and delete all files and upload new ones programatically.
i have searched and found many ways but all are for AzureStorage or using Kudu consol or FTP while what i realy want is to access the local storage where the website is deployed programatiacally, and make some edits on files programatically.
Sure thing, the Site Control Manager (Kudu) has an API for that, the VFS API:
https://github.com/projectkudu/kudu/wiki/REST-API#vfs
You can use either of these for authentication:
A Bearer token that you obtain from the STS (reference implementation in ARMClient)
Site-level credentials (the long ugly ones under your Web App → Properties)
Git/FTP credentials (subscription level)
Sample usage (using site-level credentials):
# Line breaks brutally used to improve readability
# /api/vfs/ is d:\home
# Append path as necessary, i.e. /api/vfs/site/app
$ curl -k https://$are-we-eating-too-much-garlic-as-a-people:6sujXXX
XXXXXXq7Zc#are-we-eating-too-much-garlic-as-a-people.scm.azurewebsites.net
/api/vfs/site/wwwroot/ill-grab-this-file-over-vfs-api.txt
There, i did it.
I'm assuming here that you want to do all that from the outside world - since you don't clearly state otherwise.
Well, in my azure code. my task was to save a excel file and upload its contents to SQL server.
I used this plain and simple to access home site.
string fileToSave = string.Format("{0}\\{1}", HostingEnvironment.MapPath(#"~\Temp"), FileUpload.FileName);
if (!Directory.Exists(HostingEnvironment.MapPath(#"~\Temp")))
Directory.CreateDirectory(HostingEnvironment.MapPath(#"~\Temp"));
FileUpload.PostedFile.SaveAs(fileToSave);
you could use something like this to delete and save a new file or other I/O operations.

Get Assembly Build Date in Azure Web Role

In an Azure web role, I want to retrieve the date/time when an assembly was build. I've seen a few tricks to do this by retrieving the linker timestamp from the PE header, but this requires you to read the Assembly.Location which doesn't seem to work in a Azure project. I get this exception:
NotSupportedException - The invoked member is not supported in a dynamic assembly
Perhaps there's a better way of getting this info. Perhaps I can grab the date/time when the Web Role was deployed? That would work for me as well.
Thanks for any help.
You are asking two separate things. It is very much possible that the time when code was compiled/build could be far different then when the role was deployed. So you may get the same date/time and may not, there is no guarantee unless you control build and deploy same time.
If your objective is to know when the role was deployed, you can add this date/time in multiple location and retrieve it in your Role specific code directly. I am not sure if there is a way to get the deployment time from the role and will look deep later.
Here are few suggestions comes in my mind immediately:
Create a "String" setting in your Service Configuration and read it in your Role specific Code. Keep in mind you can not get Service Configuration settings directly in Web Role specific W3WP.exe process as these two process run separately and need some extra coding.
You can also add Date/Time to service configuration and access either in Startup task to process further as below:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/11/09/how-to-access-service-configuration-settings-in-windows-azure-startup-task.aspx
You can add Date/Time setting in your App.Config and access it. I have described here:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/10/25/reading-configuration-entries-using-system-configuration-configurationmanager-class-in-a-windows-azure-application.aspx
In the solution you linked to, instead of doing this:
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
Try doing this:
System.Reflection.Assembly assembly = typeof(AClassInMyAssembly).Assembly;
I'm not sure that will work, but I think it might. If not, you might consider if the Assembly Version would work for your purposes.

how do I access a folder on the shared hosting space?

I am trying to upload image files to the server and it gives me an error
"System.UnauthorizedAccessException: Access to the path 'D:\Hosting\234344\html\Testingfiles\upload\813.jpg' is denied.at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)"
in the HttpHandler I have :
HttpPostedFile file = context.Request.Files["Filedata"];
string usr_id = context.Request.Form["usr_id"];// gets the JSON data from the request
string strPath = context.Server.MapPath(("/Testingfiles/upload/") + file.FileName);
string ext = Path.GetExtension(strPath);
if (ext.Equals(".jpg") || ext.Equals(".jpeg") || ext.Equals(".png"))
{
file.SaveAs(strPath);
context.Response.Write("Image uploaded successfully");
}
what am i doing wrong here?
The error message says it all. You don't have write access to that folder.
You will need to ask your hosting provider to assign write rights to that folder for the ASP .NET identity.
Also, consider if you can use a folder below ~/App_Data. This is by convention the place to store files that needs write access in ASP .NET, so many hosting providers will allow writes to this folder by default (but you would need to check yourself for your specific host to be sure).
You should try writing to ~/App_Data/ to see if that works. If it does then its just because you haven't given asp.net write permission to the /TestingFiles/Uploads/ folder.
If your control panel has Plesk on it then you can sort this out yourself by going to the FileManager and clicking the permissions button. If you look at your App_Data file permissions for reference, the actual username that you need to add will vary depending on your domain name with plesk.
Other hosting control panels may allow you to do it in different ways.
If you can't find it then you should ask your host how you set up file permissions or look in their knowledge base.
If your control panel has Plesk on it then you can sort this out yourself by going to the FileManager and clicking the permissions button.
I fixed this error by allowing IIS users full access to upload folder. No need to use App_Data folder
For Plesk 12.0 only:
No need to use App Data folder. You just have to give full control to your Application pool group IWPG(username). It will surely work. I searched for many hours and this solution worked for me .
Hope It works for others too.

Categories

Resources