All I have installed the latest ASP.NET Identitiy following http://blogs.msdn.com/b/webdev/archive/2014/03/20/test-announcing-rtm-of-asp-net-identity-2-0-0.aspx. Following the NuGet installation, I have intellisense access to the DeleteUser/DeleteUserAsync methods and the code compiles fine. However, at run-time when I invoke this method I get
Specified method is not supported.
Stack Trace:
[NotSupportedException: Specified method is not supported.]
Microsoft.AspNet.Identity.EntityFramework.UserStore`1.DeleteAsync(TUser user) +59
The cause is clear, but how can I compile this and it now execute? What do I have to do to be able to delete a user using UserManager?
The current code I am using to do this is
[AllowAnonymous]
public async Task<ActionResult> RemoveUser(string userName)
{
ApplicationUser user = null;
if (ModelState.IsValid)
{
user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user.IsAdmin != null && (bool)user.IsAdmin)
{
var userToRem = await UserManager.FindByNameAsync(userName);
IdentityResult result = await UserManager.DeleteAsync(userToRem); <- EXCEPTION
// If successful
if (!result.Succeeded)
return new HttpStatusCodeResult(HttpStatusCode.ServiceUnavailable);
}
}
return RedirectToAction("Index", "Tools");
}
I am not interested in anything fancy, all I want to do is remove a user and for some reason it is giving me a royal ball ache. Any other method would be appreciated.
Thanks for your time.
In ASP.NET Identity v1, DeleteAsync was not supported. Based on the error message you are seeing, it looks like you are referencing v1.
Try updating your ASP.NET Identity packages to v2.1.0 via Nuget.
Related
I have implemented some front end code which when a user clicks the checkout button they are redirected to a stripe page where they can input their card payment details. the code has a successful URL and failed URL. if the customer enter valid payment details - they are redirected to the successful URL, i need to update my database to ensure that my backend knows that this specific user has paid and can now view subscribed content. I am trying to setup web hooks in order to do this, so I know if the user has paid, cancelled etc.
using System;
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace workspace.Controllers
{
[Route("api/[controller]")]
public class StripeWebHook : Controller
{
// You can find your endpoint's secret in your webhook settings
const string secret = "whsec_...";
[HttpPost]
public async Task<IActionResult> Index()
{
var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
try
{
var stripeEvent = EventUtility.ConstructEvent(json,
Request.Headers["Stripe-Signature"], secret);
// Handle the checkout.session.completed event
if (stripeEvent.Type == Events.CheckoutSessionCompleted)
{
var session = stripeEvent.Data.Object as Checkout.Session;
// Fulfill the purchase...
HandleCheckoutSession(session);
}
else
{
return Ok()
}
}
catch (StripeException e)
{
return BadRequest();
}
}
}
}
However when trying to implement this I get errors because I think the custom code provided above uses .NET Core and I am using the full .NET framework.
Is there a way around this or what am I doing wrong?
This may help someone so I'm posting even although it's a bit late to the table as I couldn't find a relevant answer anywhere.
I had this same issue on a dotNet Core MVC web application (so not an exact answer for the question which is .Net Framework) where the Stripe Webhook was constantly giving a 400 Bad Request response. I just couldn't hit it no matter what I tried.
Eventually, and probably obviously the solution for me was to add the [IgnoreAntiforgeryToken] attribute to the Index() method as you have in your question above. As .dotNet Core enables the Validation Token on forms I had to explicitly ignore it. The Webhooks worked as soon as I did that.
So the solution for me was:
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Index()
This apparently applies to dot Net Core versions: see Microsofts Documentation
Hope this helps someone.
That's works in my Asp.net Framework 4.7, try below code for the webhook
[HttpPost]
[Route("api/[controller]/webhook")]
public async Task<HttpResponseMessage> ProcessRequest()
{
var json = await new StreamReader(HttpContext.Current.Request.InputStream).ReadToEndAsync();
try
{
var stripeEvent = EventUtility.ParseEvent(json);
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded)
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
}
else if (stripeEvent.Type == Events.PaymentMethodAttached)
{
var paymentMethod = stripeEvent.Data.Object as PaymentMethod;
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
}
// ... handle other event types
else
{
// Unexpected event type
Console.WriteLine("Unhandled event type: {0}", stripeEvent.Type);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (StripeException e)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
//Modification and Saving Data
}
After adding this webhook , you can test on locally from https://stripe.com/docs/webhooks/test this link
My Post method
[HttpPost]
public async Task<IActionResult> Register()
{
User user = new User { Email = "asfa#gmail.com", UserName = "asfa#gmail.com" };
var result = await _userManager.CreateAsync(user, "SS22!faasd");
if (result.Succeeded)
{
// install cookie
await _signInManager.SignInAsync(user, false);
}
else
{
foreach (var error in result.Errors)
{
//how can i see my errors here
}
}
return Ok();
}
I am trying to create user with UserManager and CreateAsync method, but it doesn't work. In postman I always get 200 OK.
UserManager is connected to my database, because I can get my users with get method.
Also I dont have any cshtml files, so I cant output errors on page.
In postman I always get 200 OK.
You are always getting 200 OK because at the end of a method you are returning OK() method.
In order to have some other status messages consider checking if the user is created and only then return OK() method otherwise either throw an exception, like this:
throw new ArgumentException("Wasn't able to add user")
or return some HTTPError, like this:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Not able to create user");
Note: you can also throw an exception if the user already exists when you try to add a new user.
I am trying to create user with UserManager and CreateAsync method, but it doesn't work.
This is connected with your _userManager.CreateAsync methods logic. Please revisit it.
To find error, I return OK(result), and see this error in postman.
I'm encountering a problem. I am using Microsoft Graph to get the current logged in user via OnBehalfOfMsGraphAuthenticationProvider.cs as seen in the following solution.
This has been working flawlessly, but I have been doing some refactoring, and suddenly I get an error when trying to execute my authContext.AcquireTokenAsync() method.
HTTP Error 502.3 - Bad Gateway
The code in question looks like this:
public async Task AuthenticateRequestAsync(HttpRequestMessage request) {
var httpContext = _httpContextAccessor.HttpContext;
//Get the access token used to call this API
string token = await httpContext.GetTokenAsync("access_token");
//We are passing an *assertion* to Azure AD about the current user
//Here we specify that assertion's type, that is a JWT Bearer token
string assertionType = "urn:ietf:params:oauth:grant-type:jwt-bearer";
//User name is needed here only for ADAL, it is not passed to AAD
//ADAL uses it to find a token in the cache if available
var user = httpContext.User;
string userName =
user.FindFirst(ClaimTypes.Upn).Value ?? user.FindFirst(ClaimTypes.Email).Value;
var userAssertion = new UserAssertion(token, assertionType, userName);
//Construct the token cache
var cache = new DistributedTokenCache(user, _distributedCache,
_loggerFactory, _dataProtectionProvider);
var authContext = new AuthenticationContext(_configuration["AzureAd:Instance"] +
_configuration["AzureAd:TenantId"], true, cache);
var clientCredential = new ClientCredential(_configuration["AzureAd:ClientId"],
(string) _configuration["AzureAd:ClientSecret"]);
//Acquire access token
var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, userAssertion); //This is where it crashes
//Set the authentication header
request.Headers.Authorization = new AuthenticationHeaderValue(result.AccessTokenType, result.AccessToken);
}
I am calling it from my OrdersController:
// POST: api/Orders
[HttpPost]
public async Task<IActionResult> CreateAsync([FromBody] OrderDTO order) {
if (!ModelState.IsValid) {
return BadRequest(ModelState);
}
var graphUser = await this.graphApiService.GetUserProfileAsync();
The refactoring has consisted of dividing my solution into two class library projects and one web project - the latter has the controllers and the React app. GraphAPiClient and the provider are located in the Core library like this:
Screenshot of architecture
So, it turns out that the problem appeared when I upgraded the package Microsoft.IdentityModel.Clients.ActiveDirectory from v3.19.8 to v4.4.1. For some reason, no versions above v3.19.8 work with my code, causing it to crash when I try to make the call to https://graph.microsoft.com, but as soon as I downgraded the problem disappeared.
Try using AcquireToken instead of AcquireTokenAsync
azureAuthenticationContext.AcquireToken
So, I tried following the instructions here to implement an action on my Job entity, but for the life of me, I can't get OData to recognize it.
The Action is pretty simple. Just a toggle for a boolean:
[HttpPost]
public IHttpActionResult Pause([FromODataUri]int key)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
Job job = _context.Job.Find(key);
if (job == null)
{
return NotFound();
}
job.IsPaused = !job.IsPaused;
_context.SaveChanges();
return Ok(acquisition.IsPaused);
}
And it is defined in my WebApiConfig as:
var jobEntity = builder.EntityType<Job>();
var pause = jobEntity.Action("Pause");
pause.Returns<bool>();
So, I should be able to POST to //url/odata/Job(key)/Pause to call it. Unfortunately, it doesn't recognize the Pause action, listing it with a response of entityset/key/unresolved action. If I try to use the ODataRoute attribute on it:
[ODataRoute("Job({key})/Pause")]
It chokes on the Pause, giving me a compile error of "The path template 'Job({key})/Pause' on the action Pause in controller 'Job' is not a valid OData path template. Found an unresolved path segment 'Pause' in the OData path template."
Now, if I make it an unbound action:
var pause = builder.Action("Pause");
pause = Parameter<int>("key");
pause.Returns<bool>();
and
[HttpPost]
[ODataRoute("Pause")]
public IHttpActionResult Pause(ODataActionParameters parameters)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
var key = Convert.ToInt32(parameters["key"]);
Job job = _context.Job.Find(key);
if (job == null)
{
return NotFound();
}
job.IsPaused = !job.IsPaused;
_context.SaveChanges();
return Ok(acquisition.IsPaused);
}
It works just fine. So, why can't I bind this to the Job entity? Just as a note I did try adding ODataActionParameters, even tho I don't have any parameters to see if that changed anything. It didn't.
FYI the bound to entityset examples, from that, you can see that you need a namespace, you should request like: odata/Job(key)/Default.Pause, bound action doesn't need ODataRoute.
I'm also struggling with it...
I tried to apply the Fan Ouyang's suggestion without success...
http://odata.github.io/WebApi/#04-07-action-parameter-support
OData route config:
EntityTypeConfiguration<tblMeetings> MeetingsType = builder.EntitySet<tblMeetings>("Meetings").EntityType;
MeetingsType.HasKey(p => p.Meeting_ID);
var MeetingsFunctionBadges = MeetingsType.Collection.Function("Badges");
MeetingsFunctionBadges.Parameter<int>("key");
MeetingsFunctionBadges.Returns<List<tblBadges>>();
The meeting's controller:
[HttpGet]
[ODataRoute("Meetings({key})/Badges")]
public IHttpActionResult GetBadges(ODataActionParameters parameters)
{
return Ok();
}
An then the error...
An exception of type 'System.InvalidOperationException' occurred in
System.Web.OData.dll but was not handled in user code
Additional information: The path template 'Meetings({key})/Badges' on
the action 'GetBadges' in controller 'Meetings_OData' is not a valid
OData path template. Found an unresolved path segment 'Badges' in the
OData path template 'Meetings({key})/Badges'.
in ASP MVC5 RC I didn't get the role system to work.
My database has all needs tables an role exist but proofing if user is in role always return false (no SQL exception or something)!?
Did I need to activate role system for IPrincipal somewhere?
Test code:
AccountController accCont = new AccountController();
// check role exist : result = true
var roleExist = await accCont.IdentityManager.Roles.RoleExistsAsync("61c84919-72e2-4114-9520-83a3e5f09de1");
// try find role by name : result = role object
var role = await accCont.IdentityManager.Roles.FindRoleByNameAsync("ProjectAdministrator");
// check with AccountController instance : result = true
var exist = await accCont.IdentityManager.Roles.IsUserInRoleAsync(User.Identity.GetUserId(), role.Id);
// check if current user is in role : result (both) = false????
var inRole = User.IsInRole(role.Id);
var inRole2 = User.IsInRole(role.Name);
I also try to build an custom extenuation like the IIdentity.GetUserId() extension method from Microsoft.AspNet.Identity.Owin Namespace.
namespace Microsoft.AspNet.Identity
{
public static class IdentityExtensions
{
public static string IsUserInRole(this IIdentity identity)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
ClaimsIdentity identity2 = identity as ClaimsIdentity;
if (identity2 != null)
{
var result = identity2.FindFirstValue(IdentityConfig.Settings.GetAuthenticationOptions().RoleClaimType);
return null; // later result
}
return null;
}
}
}
But the result for claim Type RoleClaimType is always null :(
I'm really stuck with this.
Thank you for your help! Steffen
I'm trying to understand how to use roles in MVC 5 myself, which is what brought me here. I can't answer your question, but check out this link. The downloaded solution works right out of the box and I've already been able to cut-and-paste some of the code and get it working in my own app. Now I'm trying to fully understand what it's doing.
http://www.typecastexception.com/post/2013/11/11/Extending-Identity-Accounts-and-Implementing-Role-Based-Authentication-in-ASPNET-MVC-5.aspx
It may not answer your question but at least it's a fully working solution that actually does work as described without a lot of hassle, so it's a good starting point.
User.IsInRole is basically looking at the claims for the currently signed in user. What does your sign in logic look like? That is what is responsible for minting the cookie that turns into the User identity. That needs to have the Role claim set properly for the IsInRole method to work correctly.