User.Identity.Name in Web Api Controller - asp.net-mvc

I went through the answer to some of the already existing questions and none of the answers are working for me.
In the ProfileController, I invoke the WebApi Controller as follows:
public ViewResult Index()
{
var client = new HttpClient();
var webApiUrl = ConfigurationManager.AppSettings["WebApiURL"];
var response = client.GetAsync(string.Format("{0}{1}", webApiUrl, "//api/ProfileWeb")).Result;
var profile = response.Content.ReadAsAsync<Profile>().Result;
if (profile != null)
{
_profileModel.Id = profile.Id;
_profileModel.FirstName = profile.FirstName;
_profileModel.LastName = profile.LastName;
_profileModel.PhoneNumber = profile.PhoneNumber;
_profileModel.EmailAddress = profile.EmailAddress;
}
return this.View(_profileModel);
}
In the Api Contoller, I get the userName as follows:
public class ProfileWebController : ApiController
{
private IReminderDb _db;
public ProfileWebController(IReminderDb db)
{
_db = db;
}
public object Get()
{
string userName = User.Identity.Name; // <-- Not working..
var profile = _db.GetProfile(userName);
return profile;
}
}
Inside the web api controller, I am not able to get the User.Identity.Name that is in the ProfileContoller. According to some other answers where I have tried Thread.CurrentPrincipal but still the User.Identity.Name is coming out as null in web api controller.
What am I missing?

Related

How to mock HttpContext in ASP.NET Core [duplicate]

This question already has answers here:
Error trying to create Mock.Of<ControllerContext>() for ASP.Net Core 3.1 Unit Test
(2 answers)
Closed 1 year ago.
I'm trying to mock HttpContext to test my UsersController.
The UsersController inherit from
public abstract class ControllerBase
and HttpContext is a property of ControllerBase
public HttpContext HttpContext { get; }
and here is the method in the UsersContoller, which I want to test
public async Task<IActionResult> Register([FromBody] UserViewModel model)
{
_logger.LogDebug("Register new user");
var user = mapper.Map<User>(model);
user.Company.Active = false;
var result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await userManager.AddToRoleAsync(user, Roles.NO_ACCESS);
//send confirmation email
string confirmationToken = userManager.GenerateEmailConfirmationTokenAsync(user).Result;
HostString hostString = HttpContext.Request.Host; //I need to mock httpcontext for this
this.mailSender.SendConfirmationMailAsync(user, hostString, confirmationToken);
return Ok();
}
else
{
_logger.LogInformation("User could not be registered Errors:");
result.Errors.ToList().ForEach(e => _logger.LogInformation(e.Description));
return BadRequest(result.Errors);
}
}
this is my BaseTestContoller, in which setup for tests is initialized
[SetUp]
public void Setup()
{
var dbContext = CreateDbContext();
CreateUserManager();
CreateMailSender(dbContext);
CreateMockImapper();
CreateMockIlogger();
usersController = new Mock<UsersController>(
userManagerMock.Object,
new CompanyService(dbContext),
mailSenderMock,
new Mock<IConfiguration>().Object,
iMapperMock.Object,
iLoggerFactoryMock.Object);
}
i've tried many options, but it wasn't successful therefor it would be nice if someone could help me.
Thanks in advance
UPDATE
usersController = new Mock<UsersController>(
userManagerMock.Object,
new CompanyService(dbContext),
mailSenderMock,
new Mock<IConfiguration>().Object,
iMapperMock.Object,
iLoggerFactoryMock.Object);
var conterllerContext = new ControllerContext() { HttpContext = new DefaultHttpContext() { } };
HostString host = new HostString("test.de");
conterllerContext.HttpContext.Request.Host = host;
usersController.Setup(c => c.HttpContext).Returns(conterllerContext.HttpContext);
Now i have a problem with setting up.
userController.setup returns this msg :
System.NotSupportedException : Unsupported expression: c => c.HttpContext
Non-overridable members (here: ControllerBase.get_HttpContext) may not be used in setup / verification expressions.
You can use ControllerContext to set the context to be DefaultHttpContext which you can modify to your needs.
var ctx = new ControllerContext() { HttpContext = new DefaultHttpContext()};
var tested = new MyCtrl();
tested.ControllerContext = ctx;
Can't you make a mock service for getting the host address (I am not really familiar with mock libraries).
Something like this:
class IHostService {
string GetHost();
}
public class HostService {
// create constructor with httpcontextaccessor
public string GetHost() {
return _httpContextAccessor.HttpContext.Request.Host;
}
}
public class MockHostService {
public string GetHost() {
return "test.de";
}
}
and in your mock class you can probably add this service just like you added mailSenderMock. And in your controller you use string host = _hostService.GetHost().

create user in migration Up() using Identity Framework

I have added a migration to create a user but the code hangs when it hits userRepo.Create(...) and within this method at _userManager.Create(...)
using (UserRepository userRepo = new UserRepository())
{
User adminUser = new User() { IsActive = true, UserName =
"admin#testing.com", CompanyId = 1, Password =
"admintesting" };
adminUser.Role = new Models.Security.Role() { Id = 2 };
userRepo.Create(adminUser);
}
Create method is below
public IdentityResult Create(Model.User user)
{
var userEntity = Mapper.Map<Entity.Security.User>(user);
_dbContext.Set<Entity.Security.User>().Add(userEntity);
var result = _userManager.Create(userEntity, userEntity.Password);
DetachAllEntities();
return result;
}
_dbContext is inherited from IdentityDbContext and instantiated accordingly
UserManager<Entity.Security.User, int> _userManager = new UserManager<Entity.Security.User, int>(new UserStore<Entity.Security.User, Entity.Security.Role, int, Entity.Security.UserLogin, Entity.Security.UserRole, Entity.Security.UserClaim>(_dbContext));
The equivalent async method works elsewhere in the application but I would like the non-async for the migration sake. Any help is highly appreciated.

Azure Mobile Service ListAsync hangs forever

How can I make a synchronous call to a Mobile Service Table from MVC?
When I run the following code, My application keeps hanging forever waiting the result:
public class HomeController : Controller
{
MobileServiceClient mobileClient = new MobileServiceClient("My-Mobile-Server", "My-Key");
public ActionResult Index()
{
var clientTable = mobileClient.GetTable<Clients>();
var client = clientTable.ToListAsync().Result;
if (client.Count == 0)
ViewBag.TemCliente = "Não";
else
ViewBag.Cliente = client.First().Name;
return View();
}
}
Funny, the same code in my Unit Test works perfectly.
How can I list my Mobile Service Table clients Synchronously?
It looks like the problem you're having is because you're not using await with the async methods.
public class HomeController : Controller
{
MobileServiceClient mobileClient = new MobileServiceClient("My-Mobile-Server", "My-Key");
public ActionResult Index()
{
var clientTable = mobileClient.GetTable<Clients>();
var client = await clientTable.ToListAsync().Result;
if (client.Count == 0)
ViewBag.TemCliente = "Não";
else
ViewBag.Cliente = client.First().Name;
return View();
}
}
Be sure to use this doc as a reference on best practices: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-windows-dotnet-how-to-use-client-library/

Why does one Web API method work, whereas the other does not?

One of my Web API methods works perfectly, and the other not at all.
By works perfectly, I mean this:
The other one, though, doesn't seem to even know about itself. It answers the browser request with:
The code seems to be set up the same for both of them, so I don't know why one works like a charm and the other fails so thuddily.
The pertinent code is:
CONTROLLER
public class DepartmentsController : ApiController
{
private readonly IDepartmentRepository _deptsRepository;
public DepartmentsController(IDepartmentRepository deptsRepository)
{
if (deptsRepository == null)
{
throw new ArgumentNullException("deptsRepository is null");
}
_deptsRepository = deptsRepository;
}
[Route("api/Departments/Count")]
public int GetCountOfDepartmentRecords()
{
return _deptsRepository.Get();
}
[Route("api/Departments")]
public IEnumerable<Department> GetBatchOfDepartmentsByStartingID(int ID, int CountToFetch)
{
return _deptsRepository.Get(ID, CountToFetch);
}
REPOSITORY
public class DepartmentRepository : IDepartmentRepository
{
private readonly List<Department> departments = new List<Department>();
public DepartmentRepository()
{
using (var conn = new OleDbConnection(
#"Provider=Microsoft.ACE.OLEDB.12.0;User ID=Freebo;Password=RunningOnEmpty;Data Source=C:\CDBWin\DATA\CCRDAT42.MDB;Jet OLEDB:System database=C:\CDBWin\Data\nrbq.mdw"))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT td_department_accounts.dept_no, IIF(ISNULL(t_accounts.name),'No Name provided',t_accounts.name) AS name FROM t_accounts INNER JOIN td_department_accounts ON t_accounts.account_no = td_department_accounts.account_no ORDER BY td_department_accounts.dept_no";
cmd.CommandType = CommandType.Text;
conn.Open();
int i = 1;
using (OleDbDataReader oleDbD8aReader = cmd.ExecuteReader())
{
while (oleDbD8aReader != null && oleDbD8aReader.Read())
{
int deptNum = oleDbD8aReader.GetInt16(0);
string deptName = oleDbD8aReader.GetString(1);
Add(new Department { Id = i, AccountId = deptNum, Name = deptName });
i++;
}
}
}
}
}
public int Get()
{
return departments.Count;
}
private Department Get(int ID) // called by Delete()
{
return departments.First(d => d.Id == ID);
}
If entering:
http://shannon2:28642/api/Departments/Count
in the browser works to execute the Controller's GetCountOfDepartmentRecords() method, why does entering:
http://localhost:28642/api/Departments/5/6
(or:
http://localhost:28642/api/Departments/1/5
etc) not work to execute the Controller's GetBatchOfDepartmentsByStartingID() method?
Your route is missing its parameters.
[Route("api/Departments/{ID:int}/{CountToFetch:int}")]
This question looks similar to your other question below:
Why is my Web API call returning "No action was found on the controller 'DPlatypus' that matches the request"?
If you are expecting the values to come from a non-query string part of a url, you need to define them in the route template. So, it should be
[Route("api/Departments/{id}/{countToFetch}")]
Following is a good article to read about routing and action selection in Web API:
http://www.asp.net/web-api/overview/web-api-routing-and-actions

View doesn't refresh after RedirectToAction is done

Here is my problem:
[HttpPost]
public ActionResult AddData(CandidateViewModel viewModel)
{
var newCandidateId = 0;
newCandidateId = this._serviceClient.AddCandidate(viewModel);
return RedirectToAction("DisplayCandidate",new {id=newCandidateId});
}
public ActionResult DisplayCandidate(int id)
{
var candidateViewModel= this._serviceClient.GetCandidate(id);
return View(candidateViewModel);
}
After filling the form viwemodel sends to server. After data were stored, flow is redirected to DisplayCandidate action and it goes there but page didn't refresh. I don't understand why! Help, please.
Because you are using Ajax Post
public ActionResult AddData(CandidateViewModel viewModel)
{
var newCandidateId = 0;
newCandidateId = this._serviceClient.AddCandidate(viewModel);
string ReturnURL = "/DisplayCandidate/"+newCandidateId;
return JSON(ReturnURL);
}
and in your Ajax Post Method:
Onsuccess(function(retURL){ window.location(retURL); })
This will take to the new Action and that Action will return View.
If you're using Ajax, return a script results to execute the navigation
instead of
return RedirectToAction("DisplayCandidate",new {id=newCandidateId});
try
var viewName = "/Path/ViewName";
var id = 1;
var urlNavigate = string.Format("location.href='{0}?id={1}'", viewName, id);
return new JavaScriptResult() { Script = urlNavigate };

Resources