Using WebClient in ASP.NET 5 - webclient

I am working in the VS15 beta and trying to use WebClient. While System.Net is referenced, and the intellisense suggests the WebClient class is available, on build I get the following error:
The type or namespace name 'WebClient' does not exist in the namespace 'System.Net' (are you missing an assembly reference?) MyProj.ASP.NET Core 5.0 HomeController.cs
I am doing the following simplistic code:
var client = new System.Net.
var html = client.DownloadString(url);
When I go to the definition of Web Client, it shows me the source. Not quite sure what the issue is - is WebClient moved? I am struggling to find the resolution.
Thanks!

Not sure about WebClient, but you can use System.Net.Http.HttpClient to make web requests as well.
Add these references to the project.json:
"frameworks": {
"aspnet50": {
"frameworkAssemblies": {
"System.Net.Http": "4.0.0.0"
}
},
"aspnetcore50": {
"dependencies": {
"System.Net.Http": "4.0.0-beta-*"
}
}
},
And then here's how to call it from an MVC 6 action method:
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
namespace WebApplication50.Controllers
{
public class HomeController : Controller
{
public async Task<IActionResult> Index()
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MyClient", "1.0"));
var result = await httpClient.GetStringAsync("http://www.microsoft.com");
...
return View();
}
}
}

You can still use WebClient if you only target full .NET Framework instead of .NET Core by in your project.json changing:
"frameworks": {
"dnx451": { },
"dnxcore50": { }
},
to
"frameworks": {
"dnx451": { }
},

Related

Capture Events From Microsoft.Identity.Web Login/Logout

I am using Microsoft's Authentication/Authorization platform to allow User Sign-ins from Azure AD. I would like to log these events into a database. Issue is, since this type of authentication leverages middleware I am not sure how to inject code to trigger a log event.
Please let me know if there exists documentation I haven't yet found and/or how to write up a custom injection to log these events.
Thanks!
I solved my own problem. For any potential usefulness to anyone else in the future I will add what I did below..
I set up my database according to this documentation: https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model?view=aspnetcore-5.0&tabs=visual-studio
I created this Middleware Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Identity.Web;
using Application.Models;
using Application.Data;
namespace Application.Middleware
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class EventLogCaptureMiddleware
{
private readonly RequestDelegate _next;
private readonly EventLogContext _context;
public EventLogCaptureMiddleware(RequestDelegate next, EventLogContext context)
{
_next = next;
_context = context;
}
public Task Invoke(HttpContext httpContext)
{
var eventLogModel = new EventLogViewModel
{
Timestamp = DateTime.Now,
Type = "TEST",
Method = httpContext.Request.Method,
Upn = httpContext.User.Identity.Name,
Resource = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}{httpContext.Request.Path}"
};
_context.Add(eventLogModel);
var tasks = new Task[] { _context.SaveChangesAsync() };
Task.WaitAll(tasks);
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class EventLogCaptureMiddlewareExtensions
{
public static IApplicationBuilder UseEventLogCaptureMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<EventLogCaptureMiddleware>();
}
}
}
And injected into Startup.cs likeso:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//Production Exception Handler ex: API connection failed will trigger exception routed to /Home/Error
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//Handles User Error: 401, 403, 404, etc. Errors caught must land Application side. Errors occured in API with return 500 and be routed via Exception Handler
app.UseStatusCodePagesWithReExecute("/Home/Error", "?status={0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
//Must include Authentication/Authorization under routing
app.UseAuthentication();
app.UseAuthorization();
app.UseEventLogCaptureMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}

In Swagger UI, how can I remove the padlock icon from "anonymous" methods?

I'm creating an API with .Net Core 2.1 and using JSON Web Token (JWT) for authentication.
I have 2 controllers: AuthenticationController and UserController.
I have decorated AuthenticationController with [AllowAnonymous] and UserController with [Authorize].
Swagger is working correctly: it allows me to hit the endpoints in AuthenticationController (SignUp/SignIn) without requesting authorization, and it does request JWT to hit the endpoints in UserController.
However, in Swagger UI, every endpoint of every controller shows a padlock icon as if all of them required authorization. Everything works correctly and as expected but it just bothers me that the endpoints that don't require authorization still show that padlock icon.
Is there a way to remove the padlock icon from those endpoints?
I believe that something can be done with the OperationFilter but I couldn't find a way.
Absolutly, you need to use an IOperationFilter to remove the padlock icon for the anonymous endpoints.
// AuthResponsesOperationFilter.cs
public class AuthResponsesOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
.Union(context.MethodInfo.GetCustomAttributes(true))
.OfType<AuthorizeAttribute>();
if (authAttributes.Any())
{
var securityRequirement = new OpenApiSecurityRequirement()
{
{
// Put here you own security scheme, this one is an example
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
};
operation.Security = new List<OpenApiSecurityRequirement> { securityRequirement };
operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
}
}
}
// Startup.cs
services.AddSwaggerGen(c =>
{
...
c.OperationFilter<AuthResponsesOperationFilter>();
};
Do not forget to remove any call to AddSecurityRequirement in your Startup.cs, otherwise the padlock icon would still be added to all endpoints.
this solution works for SwashBuckle 5.0.0-rc5 and .Net Core 3.1.1 Web API.
You need to :
implement an IOperationFilter interface,
add c.OperationFilter(); in your Startup.cs file
finally remove any call of AddSecurityRequirement
public class AuthResponsesOperationFilter: IOperationFilter {
public void Apply(OpenApiOperation operation, OperationFilterContext context) {
if (!context.MethodInfo.GetCustomAttributes(true).Any(x => x is AllowAnonymousAttribute) &&
!context.MethodInfo.DeclaringType.GetCustomAttributes(true).Any(x => x is AllowAnonymousAttribute)) {
operation.Security = new List < OpenApiSecurityRequirement > {
new OpenApiSecurityRequirement {
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "bearer"
}
}, new string[] {}
}
}
};
}
}
}
Install Package
Swashbuckle.AspNetCore.Filters
And then when you document your swagger you need to add the below line
options.OperationFilter<SecurityRequirementsOperationFilter >();
Here's an example from .NET 6
builder.Services.AddSwaggerGen(options => {
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "API",
Version = "v1",
Description = "API using .NET 6"
});
options.OperationFilter<SecurityRequirementsOperationFilter>();
});
In startup.cs -> services.AddSwaggerGen , you need to add c.OperationFilter<ApplyOAuth2Security>(); and add below method in stratup.cs which will enable lock/authorize icon in Swagger UI for the action methods which are marked as Authorize only.
private class ApplyOAuth2Security : IOperationFilter
{
/// <inheritdoc/>
public void Apply(Operation operation, OperationFilterContext context)
{
var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var authorizationRequired = context.MethodInfo.CustomAttributes.Any(a => a.AttributeType.Name == "AuthorizeAttribute");
if (isAuthorized && authorizationRequired)
{
operation.Security = new List<IDictionary<string, IEnumerable<string>>>
{
new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new string[] { "openid" } },
},
};
}
}
}

kendo ui grid not working with .net core

I am trying to get Kendo UI grid MVC working in a .net core, reading data from PostgreSQL database.
I set up a project, connected it to a database, scaffolded controller with appropriate views and it's working ok (meaning CRUD operations are working ok).
Now I want to hook it up with Kendo.
I followed guide from kendo website and installed successfully (although it didn't offer pro version in nugget so I had to install trial??). I added all those CSS/js files in _Layout.cshtml
this is my code in controller:
public ActionResult kendo()
{
return View();
}
// GET for Kendo
public ActionResult Categories_Read([DataSourceRequest] DataSourceRequest request)
{
return Json(GetCategories().ToDataSourceResult(request));
}
public static IEnumerable<Category> GetCategories()
{
var result = from c in _context.Categories
select new Category()
{
Id = c.Id,
Name = c.Name
};
return result;
}
this is my code in kendo.cshtml
#(Html.Kendo().Grid<Category>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.Id).Title("id");
columns.Bound(c => c.Name);
})
.HtmlAttributes(new { style = "height: 550px;" })
.Scrollable()
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Categories_Read", "Categories"))
.PageSize(20)
)
Model is simple
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
The problem is that there is no data displayed in kendo grid. I can see in debugger that there is request going forward and data coming backwards but nothing is shown in grid.
?
The problem is most probably caused by the new ASP.NET Core serialization mechanism. Follow the guidelines in the "second" Step 4 here:
http://docs.telerik.com/kendo-ui/aspnet-mvc/mvc-core/getting-started
Step 4 Open Startup.cs, using a text editor (IDE) and update it as described below.
Locate the ConfigureServices method and add a call to services.AddKendo at the end.
public void ConfigureServices(IServiceCollection services)
{
...
// Maintain property names during serialization. See:
// https://github.com/aspnet/Announcements/issues/194
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
// Add Kendo UI services to the services container
services.AddKendo();
}
Locate the Configure method and add a call to app.UseKendo at the end.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
// Configure Kendo UI
app.UseKendo(env);
}
UPDATE
In order to verify that the above configuration is applied, check the server response and see if it has the following structure and letter casing for Data and Total:
{
"Data": [
{ "Id": "1", "Name": "Name 1" },
{ "Id": "2", "Name": "Name 2" }
],
"Total": "2"
}
I had the same problem in a .net core 3.1 project, the solution here is to add the following lines in Startup.cs:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
services.AddKendo();

How do you add notifcationhubs library

How do you include notificationhubs library to azure function? This is my attempt and it doesn't work
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.Azure.NotificationHubs;
public static void Run(string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
Notification a;
}
We'll add NotificationHubs to the list of built in assemblies, but for now you can add a package reference to NoficationHubs by adding a project.json file for your Function (as described in the documentation here).
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.Azure.NotificationHubs": "1.0.5"
}
}
}
}
With that in place you can add a using statement for NotificationHubs, e.g.:
using System.Net;
using Microsoft.Azure.NotificationHubs;
public static HttpResponseMessage Run(
HttpRequestMessage req,
TraceWriter log,
out Notification notification)
{
log.Info($"C# HTTP trigger function RequestUri={req.RequestUri}");
// TODO
notification = null;
return req.CreateResponse(HttpStatusCode.OK);
}

Asp.net 5.0 MVC6 EF6 Migration Scripts

I am working on Asp.net 5.0 mvc6 and I am wanting to use entityframework 6 because 7 isn't completely coded yet and I have been able to get it to do everything but migration.
When I type enable-migration, add-migration or update-datatabase I get
enable-migration : The term 'enable-migration' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ enable-migration
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (enable-migration:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I'm pretty sure these commands are not in powershell. I did however find that there are tools in %userdir%.dnx\packages\EntityFramework\6.1.3\tools. Researching migrate.exe a little bit the little I did find they told me that it only works with proj files and so doesn't work with the new setup.
I have also tried to go the programming route with this code in the constructor of dbcontext I have:
var configuration = new MigrationConfiguration();
var migrator = new DbMigrator(configuration);
migrator.Configuration.TargetDatabase = new DbConnectionInfo(nameOrConnectionString, "System.Data.SqlClient");
if (migrator.GetPendingMigrations())
{
migrator.Update();
}
and this code in my confirmation script:
public MigrationConfiguration()
{
AutomaticMigrationsEnabled = true;
MigrationsAssembly = Assembly.GetAssembly(typeof(InitialCreate));
MigrationsNamespace = "[Namespace of my migration scripts]";
}
Before I made any of this the database made a __migrationHistory table with an 201509291902537_InitialCreate in it, so I made one file with that name and made another called 201509291902538_test they both look like this:
201509291902537_InitialCreate:
namespace Infrastructure.EF.Migrations
{
using System.Data.Entity.Migrations;
public partial class InitialCreate : DbMigration
{
public override void Up()
{
}
}
}
201509291902538_test:
namespace Infrastructure.EF.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class test: DbMigration
{
public override void Up()
{
Sql("insert into LegalEntity (Id, Name ) values(" + Guid.NewGuid() + ", 'Test'");
}
}
}
No matter what I tried migrator.GetPendingMigrations() never says it has any new updates and if I made a fake update and tell it exactly what it needs to update it still doesn't work it just throws a null reference exception on the update function.
Here's my fake migrator:
namespace Infrastructure.EF.Contexts
{
public class Migrator : DbMigrator
{
public Migrator(DbMigrationsConfiguration configuration) : base(configuration)
{
}
public override IEnumerable<string> GetDatabaseMigrations()
{
return new List<string>() { "InitialCreate" };
}
public override IEnumerable<string> GetLocalMigrations()
{
return new List<string>() { "InitialCreate", "test" };
}
public override IEnumerable<string> GetPendingMigrations()
{
return new List<string>() { "test" };
}
}
}
project.json:
{
"version": "1.0.0-*",
"dependencies": {
"Autofac.Framework.DependencyInjection": "4.0.0-beta5-*",
"AutoMapper": "4.0.4",
"EntityFramework": "6.1.3",
"log4net": "2.0.3",
"Microsoft.AspNet.Http.Abstractions": "1.0.0-beta5",
"Microsoft.CSharp": "4.0.0-*",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta5",
"RestSharp": "105.2.3",
"System.Linq": "4.0.0-*",
"System.Runtime": "4.0.10-*",
"System.Threading": "4.0.10-*"
},
"frameworks": {
"dnx451": {
}
},
"configurations": {
"DV": { },
"QA": { },
"TR": { },
"PR": { }
}
}
I have tried it with both the class name and the file name and neither seems to work.
Has anybody had any luck with any of these things or see what I'm doing wrong with one of them?
If you want to use EF6 with ASP.NET MVC6, then expose EF6 repositories as Web API 2 in .NET 4.5 and consume them in ASP.NET MVC6.
I know its lots of additional work, I followed this approach to learn and develop MVC6 applications because of existing EF6 data access layer and similar issues in EF6 to EF7 migrations.
Have you tried this: http://www.bricelam.net/2014/09/14/migrations-on-k.html ?
It's for EF 7, but I think you could just change the version to EF6.