Is it possible to use the following SDK for a Web Application:
https://github.com/box/box-windows-sdk-v2
The specs say it is targeted for the .NET framework for Windows and Windows Phone applications, but I wasn't able to figure it out for a Web .NET project. Is this SDK strictly for native Windows and Windows phones applications?
I've never used await/async functions in C# and that's possibly where I can't figure it out. I've been able to successfully get an oauth2 token/refresh token, but don't know where to go from here. Could anyone take a look or provide a sample of how to retrieve folder details?
Thanks !
It is absolutely possible to use the Box Windows SDK in an ASP.NET web application.
I've recently updated the readme documentation to mention that the SDK supports the .NET 4.0 framework, so as long as your project is targeting that framework or above you should be good to go. If you are running an express version of Visual Studio, you unfortunately will not be able to open the SDK source project as it's built as a PCL (Portable Class Library). You can, however, still get the binaries through nuget.
One important thing you have to remember when using async/await calls in ASP.NET is that you have to include the Async="true" attribute in your Page declaration:
<%# Page Language="C#" Async="true" %>
You mentioned that you were able to successfully get OAuth2 tokens/refresh tokens. I'm not sure if you wrote your own workflow to retrieve those tokens, but the SDK supports handling the second step of exchanging an auth code for tokens as follows:
public async Task Authenticate(string authCode)
{
BoxConfig config = new BoxConfig("YOUR_CLIENT_KEY", "YOUR_CLIENT_SECRET", new Uri("YOUR_REDIRECT"));
BoxClient client = new BoxClient(config);
await client.Auth.AuthenticateAsync("authCode");
}
Note that when using async/await, you must decorate your method signature with the "async" keyword. Microsoft has written great articles on further understanding the async/await keywords.
In the case that you built your own OAuth2 workflow, the SDK also accepts a completed OAuth Session. Here's a full sample of that, and an example of getting items in your root level folder:
public partial class WebForm1 : System.Web.UI.Page
{
BoxClient _client;
protected async void Page_Load(object sender, EventArgs e)
{
BoxConfig config = new BoxConfig("YOUR_CLIENT_KEY", "YOUR_CLIENT_SECRET", new Uri("https://YOUR_REDIRECT"));
BoxClient client = new BoxClient(config);
OAuthSession session = new OAuthSession("YOUR_ACCESS_TOKEN", "YOUR_REFRESH_TOKEN", 3600, "bearer");
_client = new BoxClient(config, session);
}
protected async void Button_Click(object sender, EventArgs e)
{
BoxFolder folder = await _client.FoldersManager.GetItemsAsync("0", 10);
string test = folder.Name;
}
}
Related
I have opened a test project (.NET 6, VS2022) based on ASP.NET Core MVC and views template (not Razor pages), with activated individual user accounts.
Program.cs looks like this (from the template):
builder.Services.AddDefaultIdentity<IdentityUser>(options ...
builder.Services.AddControllersWithViews();
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
So far so good.
Now I added some example code to seed the user database, which needs access to the RoleManager:
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();`
However, that throws an exception
No service for type Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]'
which could be fixed (thanks Stackoverflow) by changing the AddDefaultIdentity() to AddIdentity() which introduces IdentityRole:
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options ...
However, now I get an exception further down with
app.MapRazorPages();
System.InvalidOperationException: 'Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddRazorPages' inside the call to 'ConfigureServices(...)' in the application startup code.'
Which services need to be configured and how?
When I remove app.MapRazorPages();, the user management pages (login, user registration) do no longer work (404 error).
When I instead add builder.Service.AddRazorPages() above, the routing is also broken: a route to "/account/login" is missing, probably because Razor pages are somewhat differently organized than MVC controllers. Obviously, I do not want Razor pages, just Razor logic in a few views, and basically MVC architecture.
I am, honestly, a bit confused, since the official documentation does not help much.
Follow your document, I fount that what you did is adding an initialization to create data in the database. So I created a new .net 6 MVC app and integrate default authentication. Pick up Authentication type field with Individual User Accounts when creating the project, then run Update-Database command in Package Manager Console window. Now I have a empty .net 6 MVC project with default asp.net core authentication.
Next, I followed the document and created a SeedData.cs file in the root folder:
using Microsoft.AspNetCore.Identity;
namespace WebAppDefIdentity
{
public static class SeedData
{
//public const string AdministratorRole = "Administrator";
public static async Task InitializeAsync(IServiceProvider services) {
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await EnsureRolesAsync(roleManager);
}
private static async Task EnsureRolesAsync(RoleManager<IdentityRole> roleManager)
{
var alreadyExists = await roleManager.RoleExistsAsync("Administrator");
}
}
}
And the document is .net 5 oriented project, so need a little change. In the Program.cs file, adding following codes.
using (var scope = app.Services.CreateScope())
{
var aa = scope.ServiceProvider;
await SeedData.InitializeAsync(aa);
}
Then I reproduce your first exception
To solve this exception, I changed in Program.cs with code .AddRoles<IdentityRole>()
Then no exception.
I have a simple set up:
Azure Web App, running a static react app
Azure Functions App, the API layer that accesses the database and that is called from the static web app
Both Web App and Functions App have a deployment slot feature, where you deploy in a separate slot first and if everything works well, you can swap the artifact in your slot and the current version, with no downtime. I really want to use this to its fullest.
I'd like to use the Web App configuration to inject the root uri of the API, have it point to the API in the corresponding slot. So the production-staging static site, should point to the production-staging API.
But here's the main problem: I cannot access the Web App configuration from my react app. I have to insert the root uri at build time, which disables the swap feature for the Web App (since it would still be pointing to staging).
Accessing the configuration works fine for the Functions App; I'm assuming because it's running node.
The Web App Configuration are available as environment variables on the server. You won't be able to access those variables within your static react app that is running on the client.
You will need some kind of middleware that is able to read and expose the environment variables through an API.
You can use ASP.NET Core with the React project template to create both, an ASP.NET Core project that acts as an API and a standard CRA React project to act as a UI, but with the convenience of hosting both in a single app project that can be built and published as a single unit. (Source).
Then you will have to write a little controller that exposes the configurations. Here an example:
public class MyOptions
{
public string ApiUri { get; set; }
}
[ApiController]
[Route("[controller]")]
public class ConfigurationController : ControllerBase
{
private readonly MyOptions _options;
public ConfigurationController(IOptions<MyOptions> options)
{
_options = options.Value;
}
[HttpGet]
public MyOptions GetConfigurations()
{
return _options;
}
}
You also need to configure the options within the startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration.GetSection(nameof(MyOptions)));
services.AddControllers();
}
Now you can set your initial value within the appsettings.json:
{
"MyOptions": {
"ApiUri" : "https://myapp.domain.com/api"
}
}
And you are also able to overwrite the options using the Azure Web App Configurations (the middleware is configured to also use environment variables and that environment variables overwrite appsettings.json)
Now the last thing you have to do is to retrieve the settings within your static UI using:
window.location.host + "/api/configuration"
Client code cannot access appsettings.json. In react you can use.env files to store your configurations. You can create.env files for each environment you want to support and in the build script you can mention which.env file to use for each environment.
How can you generate emails (html) using Razor in dotnetcore - and not from an MVC app (think from a console app)?
RazorEngine does a great job in .net 4.x, but is not working in dotnet core.
RazorEngineLight works in dotnet core 1.x, but not in 2.x.
Some other options are mentioned in this post: Using Razor outside of MVC in .NET Core but none of them actually work in .net core 2.0
Edit two years later:
In case somebody comes here looking for answers on this... I (OP) have stopped entirely relying on Razor to generate emails using templates etc. It is very fragile and error-prone - a non-stop headache. I prefer Mandrill or Sendgrid these days - using templates.
In a comment on this provided answer from the link provided you stated
I am not able to get this to work. I get the error: Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine' while attempting to activate 'Mvc.RenderViewToString.RazorViewToStringRenderer'.'
This normally indicates that a required service was not registered with the service collection so the provider is unable to resolve the service when needed.
That answer did not refer to the additional service configuration and only had
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IViewRender, ViewRender>();
}
as it was already being run in an Asp.Net Core environment, which meant that the services manually added in the console application were already being done in start up.
Pay attention to this snippet from the answer that was linked to from the answer you commented on.
private static void ConfigureDefaultServices(IServiceCollection services) {
var applicationEnvironment = PlatformServices.Default.Application;
services.AddSingleton(applicationEnvironment);
var appDirectory = Directory.GetCurrentDirectory();
var environment = new HostingEnvironment
{
WebRootFileProvider = new PhysicalFileProvider(appDirectory),
ApplicationName = "RenderRazorToString"
};
services.AddSingleton<IHostingEnvironment>(environment);
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Clear();
options.FileProviders.Add(new PhysicalFileProvider(appDirectory));
});
services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
services.AddSingleton<DiagnosticSource>(diagnosticSource);
services.AddLogging();
services.AddMvc();
services.AddSingleton<RazorViewToStringRenderer>();
}
The important part above is
services.AddMvc();
That will add the relevant view engine dependencies to the service collection
MvcServiceCollectionExtensions.cs
public static IMvcBuilder AddMvc(this IServiceCollection services) {
//...code removed for brevity
// Default framework order
builder.AddFormatterMappings();
builder.AddViews();
builder.AddRazorViewEngine();
builder.AddRazorPages();
builder.AddCacheTagHelper();
//...code removed for brevity
}
Everything else as currently presented is sound and should work as intended.
You should review
https://github.com/aspnet/Entropy/tree/93ee2cf54eb700c4bf8ad3251f627c8f1a07fb17/samples/Mvc.RenderViewToString
and follow a similar structure to get the code to work in your scenario. From there you can start making your custom modification and monitor where it breaks.
The modular nature of .Net Core allows for such customizations as the different modules can be stripped out and used in other environments.
I've just started digging into the new ASP.NET 5 by creating a test single page application with the OAuth login. I already know that I can use IdentityServer3 for that purpose and it seems pretty nice. I've found a post by Dominick Baier which is explaining how to set up the IdentityServer3. However, the post seems to be out of date or the identity server itself isn't working with the latest version of the ASP.NET 5 (which is beta7 at the moment).
The problem is, when I try to configure the IdentityServer in the Startup.cs I got an error from VS telling me that IApplicationBuilder has no extension method called UseIdentityServer. And this seems to be true, since in the IdentityServer3 source code they have this extension method declared for IAppBuilder (not IApplicationBuilder).
Here is my code (Startup.cs):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// Add MVC to the request pipeline.
app.UseMvc();
var options = new IdentityServerOptions
{
Factory = new IdentityServerServiceFactory()
};
app.UseIdentityServer(options);
}
And the error (on the last line) is
'IApplicationBuilder' does not contain a definition for 'UseIdentityServer' and the best extension method overload 'UseIdentityServerExtension.UseIdentityServer(IAppBuilder, IdentityServerOptions)' requires a receiver of type 'IAppBuilder'
Obviously, if I change the parameter type in the Configure method to IAppBuiler, it'll throw a runtime error because the dependency injection will not be able to inject that type. Even if it would, I'd lose the UseMvc() extension method.
So could you point me in the right direction please?
Perhaps I'm just missing something tiny but crucial here.
Thanks in advance!
I am trying to host a windows forms control in C# inside an html page and then host that web page in IIS in order to be accessible by other client machines.
The problem is: the user control uses some unmanaged code, which triggers a SecurityPermissionException when accessing using another machine.
I've managed to dumb down my code to an elementary example in order to pinpoint the error and I just can't seem to find an answer to this.
Here's my user control:
// To handle strong named assembly
[assembly: AllowPartiallyTrustedCallers]
namespace WinFormsHTMLControl
{
[SecurityPermissionAttribute(SecurityAction.Assert, UnmanagedCode = true)] // to allow assertions regarding unmanaged code permissions
public partial class HelloWorldControl : UserControl
{
#region Methods/Consts for Embedding a Window
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
#endregion
public HelloWorldControl()
{
InitializeComponent();
}
private void btnClick_Click(object sender, EventArgs e)
{
new SecurityPermission(PermissionState.Unrestricted).Assert();
IntPtr picBoxHandle = FindWindow("IEFrame", "Internet Explorer");
lblMessage.Text = picBoxHandle.ToString();
SecurityPermission.RevertAssert();
}
}
}
I've signed the assembly with a key, I've created a Permission Set in .NET Configuration Tool in order to grant acess to unmanaged code, and created a CodeGroup pointing to the strong key used to name the assembly.
I've also created an MSI in order to copy these settings to other machines (i've done this both at Enterprise and Machine levels).
Despite all this, this code still triggers a SecurityPermissionException when I click the button...
Am I missing something here?
IE is sandboxed and you're trying to perform an operation that you can't perform-- ie, calling directly into user32 from a website. Imagine how dangerous the internet would be if anybody could do that on any website. Your core architecture is flawed.