Value cannot be null. Parameter name: routeCollection + ApiController - asp.net-mvc

In another project an ASP.NET MVC 5 controller, the AccountController inherits from the Controller class. Within this class when I attempt to generate a URL to reset a user's password I have the following implementation.
// Send an email with this link
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
However, I moved my logic to a Web API project where the AccountController interits from the ApiController class. In an effort to generate the URL to reset the user's password, I have the following implementation:
var _url = new System.Web.Mvc.UrlHelper();
var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = _url.Action("ResetPassword", "Account", new { UserId = user.Id, code = code }, Request.RequestUri.Scheme);
With this later implementation, where the AccountController : ApiController, I get an error:
"ExceptionMessage": "Value cannot be null.
Parameter name: routeCollection"
What am I missing?

Apparently, you have to pass an argument to the UrlHelper class as shown below
var _url = new System.Web.Mvc.UrlHelper(HttpContext.Current.Request.RequestContext);

Related

Using ASP.NET identity to do external oauth logins, how can add parameters to the facebook authorization endpoint? I want to pass "display=popup"

I'm using ASP.NET MVC 6 (.net core). With it, i'm using the built in external login logic in order to authenticate with facebook.
I've made a modification to it so that instead of authenticating within the same window, i'm launching a popup and authenticating there. Once successful, the popup closes itself and tells my main window to redirect. This all works.
However, I want to use the "smaller/mini" version of the facebook login page. This can be seen here:
https://www.facebook.com/login.php?display=popup
"display=popup" is what is controlling it.
I don't see how i can inject this kvp in my C# code. Where can i do it?
app.UseFacebookAuthentication(new FacebookOptions
{
// was hoping for something here... tried to stick it into the authorizationurl but then i end up with 2 question marks and it fails
AppId = "blah",
AppSecret = "blah"
});
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
// Don't see anything here...
return Challenge(properties, provider);
}
You can use OnRedirectToAuthorizationEndpoint event:
var facebookOptions = new FacebookOptions
{
AppId = "",
AppSecret = "",
Events = new OAuthEvents()
{
OnRedirectToAuthorizationEndpoint = ctx =>
{
ctx.HttpContext.Response.Redirect(ctx.RedirectUri + "&display=popup&pip");
return Task.FromResult(0);
}
}
};
app.UseFacebookAuthentication(facebookOptions);

Call async Task<> from controller in ASP.NET MVC

I have a Library wrapper OVH API and i try to call a function for get my consumer key in a ASP.NET MVC project. It works in a Console project application but the method never response in my Controller : the method in the Library
public async Task<CredentialsResponse> RequestCredential(IEnumerable<AccessRule> accessRules, string redirectUrl = null)
{
Ensure.NotNull("accessRules", accessRules);
CredentialsRequest cmd = new CredentialsRequest();
cmd.AccessRules.AddRange(accessRules);
cmd.Redirection = redirectUrl;
if (cmd.AccessRules.Count == 0)
throw new ArgumentException("You must specify at least one accessRule");
return await RawCall<CredentialsResponse>(HttpMethod.Post, "/auth/credential", cmd;
}
and i call in the controller :
public ActionResult Index()
{
Information infosClient = new Information();
OvhApiClient api = new OvhApiClient("", "", OvhInfra.Europe);
CredentialsResponse response = api.RequestCredential(new[]{
new AccessRule{ Method = "GET", Path = "/*"},
new AccessRule{ Method = "PUT", Path = "/*"},
new AccessRule{ Method = "POST", Path = "/*"},
//new AccessRule{ Method = "DELETE", Path = "/*"},
}).Result;
api.ConsumerKey = response.ConsumerKey;
infosClient.ConsumerKey = api.ConsumerKey;
return View(infosClient);
}
I already tried quite a lot of things without success (put the call in a method async for example).
Thanks in advance for your help
Make the controller action async:
public async Task<ActionResult> Index()
{
...
CredentialsResponse response = await api.RequestCredential(...);
...
}

Is there anyway to shorten the DpapiDataProtectionProvider Protect output?

Using the provided template for an Asp.Net OWIN MVC app. I get an AccountController with a ForgotPassword method that calls...
var code = await manager.GeneratePasswordResetTokenAsync(user.Id);
After some research I find out that the code is protected by OWIN security, using the DpapiDataProtectionProvider Protect method. Which is fine.
What's throwing me off here is the code that is being returned is super long, and I'm not sure if I'm doing it wrong or if there is something that I can change to shorten it. One important thing to note is that I am setting the IDataProtector by hand with the following code...
//ctor
public MyUserManager(IUserStore<MyUser, int> store) : base(store)
{
var provider = new DpapiDataProtectionProvider("MvcApplication");
UserTokenProvider = new DataProtectorTokenProvider<MyUser, int>(provider.Create("EmailConfirmation"));
}
Any help would be greatly appreciated!
You can't shorten DpapiDataProtectionProvider output but you can for example generate a GUID (or some other random string), substitute it in callbackUrl and save it in your DB along side with DpapiDataProtectionProvider code. Then, in a ResetPassword method, retreive original protected code from database with a provided GUID and call ResetPasswordAsync.
It could look something like this(pseudo code):
public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
string originalCode = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
string code = Guid.NewGuid().ToString(); // or other short code
/*
Save to database code and originalCode
*/
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "Reset Password", "Please reset your password by clicking here");
return RedirectToAction("ForgotPasswordConfirmation", "Account");
}
And your ResetPassword
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
/*
retreive originalCode from database by using model.Code
*/
var originalCode = from_db;
var result = await UserManager.ResetPasswordAsync(user.Id, originalCode, model.Password);
AddErrors(result);
return View();
}
Another way is to implement IDataProtector and use some other algorithm to protect and unprotect data that will be shorter in length.

RedirectToAction method with multiple route parameters not redirecting

I am using RedirectToAction method and i want to pass two route parameters
but its not redirecting to specified action method.
I am using following code:
return RedirectToAction("abcd", "Registration", new { id = "", loginType = "pqr" });
and the specified action method signature is as :
public ActionResult abcd(string id, string loginType = null)
Is there any mistake in signature??
Thanks...
Make sure that the abcd() action method is in a class called RegistrationController. If your abcd() action method is in the RegistrationController class then you want to call like this:
return RedirectToAction("abcd", new { id = "", loginType = "pqr" });

ASP.NET Web Api - post object to custom action controller

I have next ApiController
public class ValuesController : ApiController
{
// GET /api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
public User CreateUser(User user)
{
user.Id = 1000;
return user;
}
}
with next route
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
and i want to consume this service. I can consume first method:
var client = new WebClient();
var result = client.DownloadString(#"http://localhost:61872/api/values/get");
but i can't consume second method. When i do next:
var user = new User() { Name = "user1", Password = "pass1" };
var json = Newtonsoft.Json.JsonConvert.SerializeObject(user);
result = client.UploadString(#"http://localhost:61872/api/values/createuser", json);
i catch next exception without additional information
The remote server returned an error: (500) Internal Server Error.
I have a two questions:
What correct way to set custom object to service method parameter?
How can i get addition information about "magic" exception like this?
If you intend to send a JSON request make sure you have set the Content-Type request header appropriately, otherwise the server doesn't know how is the request being encoded and the user parameter that your Api controller action takes is null:
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
var user = new User() { Name = "user1", Password = "pass1" };
var json = Newtonsoft.Json.JsonConvert.SerializeObject(user);
var result = client.UploadString(#"http://localhost:61872/api/values/createuser", json);
}

Resources