Since the two following controller's actions are possible, I am wondering if there is any difference in terms of performance (or best practices) between them.
[HttpGet("example1")]
public ActionResult<User> GetExample1()
{
var user = new User { UserName = "Example 1 user" };
var model = new Model<User>(user);
return Ok(model);
}
[HttpGet("example2")]
public ActionResult<Model<User>> GetExample2()
{
var user = new User { UserName = "Example 2 user" };
var model = new Model<User>(user);
return Ok(model);
}
Please notice that the only difference between the two is the returned type of the generic parameter of ActionResult (User vs Model<User>). Is there any important internal differences when the ActionResult object is formatting out the result?.
User and Model code for this example:
public class User
{
public string UserName { get; set; }
}
public class Model<T>
{
public T Data { get; set; }
public Model(T data)
{
Data = data;
}
}
Greeting,
I have an website that display products everything okay until now but i want the current user that have logged in to get his/ her data only, eg. if the user has id=1 its will get all products will id=1 (i have foreign key constrain between the two tables) i am using very simple controller that only get all products, i didn't find any solution at google.
i am using .NET CORE 3.0 with EntityFramework and SQL SERVER database
i am currently using JWT token that is stored inside local storage at web browser.
here is my ProductsController
public class ProductsController : ControllerBase
{
private readonly IAuthRepository _repo;
private readonly DataContext _context;
public ProductsController(DataContext context, IAuthRepository repo)
{
_context = context;
_repo = repo;
}
[HttpGet]
public async Task<IActionResult> AllProducts()
{
var All = await _context.Product.ToListAsync();
return Ok(All);
}
below is the code to get userid from jwt token
var context = new HttpContextAccessor();
var principal = context.HttpContext.User;
if (null == principal)
return null;
var id = principal.FindFirstValue(ClaimTypes.NameIdentifier);
Then update your action method " AllProducts" to
[HttpGet]
public async Task<IActionResult> AllProducts()
{
var context = new HttpContextAccessor();
var principal = context.HttpContext.User;
if (null == principal)
return null;
var userid = principal.FindFirstValue(ClaimTypes.NameIdentifier);
var All = await _context.Product.where(p=>p.id==userid).ToListAsync();
return Ok(All);
}
I have created and published an Azure Function (HTTP Triggered) for a search functionality. When I type an ID in a search box and click on "Search", it should call the Azure Function and get the result back.
How to integrate the Azure Function with my Controller Action in .NETCore?
Here is the example how you could call your azure function into the controller.
I have a simple azure function which return a name and email once its called. Let's see the below example:
public class InvokeAzureFunctionController : ApiController
{
// GET api/<controller>
public async System.Threading.Tasks.Task<IEnumerable<object>> GetAsync()
{
HttpClient _client = new HttpClient();
HttpRequestMessage newRequest = new HttpRequestMessage(HttpMethod.Get, "http://localhost:7071/api/FunctionForController");
HttpResponseMessage response = await _client.SendAsync(newRequest);
dynamic responseResutls = await response.Content.ReadAsAsync<dynamic>();
return responseResutls;
}
}
Test Function For Controller Invocation:
public static class FunctionForController
{
[FunctionName("FunctionForController")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
if (name == null)
{
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
name = data?.name;
}
ContactInformation objContact = new ContactInformation();
objContact.Name = "From Azure Function";
objContact.Email = "fromazure#function.com";
return req.CreateResponse(HttpStatusCode.OK, objContact);
}
}
Simple ContactInformation Class I have Used:
public class ContactInformation
{
public string Name { get; set; }
public string Email { get; set; }
}
PostMan Test:
I have called the controller action from Post Man and its successfully return data from my local azure function through the local controller action. See the screen shot below:
Hope you understand. Just plug and play now.
I'm building an history of the action a user called. For this I need all the parameters in the original querystring. This needs to be done in the OnActionExecuted (After the action) because some description information are stored in the filterAction.Result.Model.MyDescription.
On the ActionExecutedContext I do not have access to the ActionParameters and the RoutesValues only contains action, controller, id and culture. It doesn't contains any of the other parameters that was included in the querystring.
How can I preserve the ActionParameters from the OnActionExecuting to the OnActionExecuted?
Controller:
[ReportHistoryLink]
public ActionResult Index(int id, DateTime at, string by)
{
var model = new ReportModel();
model.ReportDescription = "Some logic get the ReportDescription";
return View("Index", model);
}
ActionFilter:
public class ReportHistoryLinkAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var model = (IModelWithReportDescription)((ViewResult)filterContext.Result).Model;
var description = model.ReportDescription;
var boxedId = filterContext.RouteData.Values["id"];
var id = Convert.ToInt32(boxedId);
if (id != 0 && !string.IsNullOrWhiteSpace(targetDescription))
{
var link = new HistoryLink
{
Id = id,
Description = description,
Route = filterContext.RouteData.Values //This doesn't contains the "at and by parameters"
};
}
}
}
You can use
filterContext.HttpContext.Request.QueryString["id"]
How can I save something using FormsAuthentication? I don't want to store UserId through URL's.
For example, now I have this code:
//UserController class:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (repository.ValidateUser(model.Login, model.Password))
{
FormsAuthentication.SetAuthCookie(model.Login, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Project", "Index");
}
}
else
{
ModelState.AddModelError("", "Incorrect name or password.");
}
}
return View(model);
}
ProjectController class:
public ViewResult Index()
{
return View(repository.GetUserProjects(
this.ControllerContext.HttpContext.User.Identity.Name));
}
ProjectRepository:
ProjectsContext context = new ProjectsContext();
UsersContext uCnt = new UsersContext();
public IEnumerable<Project> GetUserProjects(String username)
{
if (String.IsNullOrEmpty(username))
throw new ArgumentNullException("username", "Login is empty");
return this.uCnt.Users
.FirstOrDefault(u => u.Login == username)
.Projects
.ToList();
}
ProjectController and ProjectRepository don't looks like good code... Maybe someone can give advise, how to store UserID without using URL's? Best way to do this is save IDs on autorisation, I think. I don't found any properties in User.Identity to do this...
UPD
I beg a pardon, but I forgot to say that I'm using MVC-3 with Razor view.
And that UserId is not a string (User.Identity.Name is a string) it could be GUID or maybe my own object...
Save the UserID in the UserData property of the FormsAuthentication ticket in the authorization cookie when the user logs on:
string userData = userID.ToString();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Email,
DateTime.Now, DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
createPersistentCookie, userData);
string hashedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashedTicket);
HttpContext.Current.Response.Cookies.Add(cookie);
You can read it back in the PostAuthenticateRequest method in Global.asax:
HttpCookie formsCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (formsCookie != null)
{
FormsAuthenticationTicket auth = FormsAuthentication.Decrypt(formsCookie.Value);
Guid userID = new Guid(auth.UserData);
var principal = new CustomPrincipal(Roles.Provider.Name, new GenericIdentity(auth.Name), userID);
Context.User = Thread.CurrentPrincipal = principal;
}
Note that in this case, CustomPrincipal derives from RolePrincipal (although if you're not using Roles, I think you need to derive from GenericPrincipal), and simply adds the UserID property and overloads the constructor.
Now, wherever you need the UserID in your app, you can do this:
if(HttpContext.Current.Request.IsAuthenticated)
Guid userID = ((CustomPrincipal)HttpContext.Current.User).UserID;
Why not first make all your authorization calls via an interface. This way all of your code which uses authentication does not need to be concerned about how the login is performed, or how the Indentity is stored, etc.
public interface IAuthorization
{
bool ValidateUser(LoginUser u, string password);
LoginUser GetCurrentUser();
void LogIn(LoginUser user);
void LogOut();
IIdentity GetCurrentUserIdentity();
}
Implemenation for the IIdentity GetCurrentUserIdentity could be any way you like, but is commonly seen as a call to "HttpContext.Current.User.Identity"
public class Authorization : IAuthorization
{
/// <summary>
/// Get the IIdentity for the current logged in user
/// </summary>
/// <returns>IIdentity</returns>
public virtual IIdentity GetCurrentUserIdentity()
{
return HttpContext.Current.User.Identity;
}
/// <summary>
/// Log the user in
/// </summary>
/// <param name="user">User details</param>
public void LogIn(LoginUser user)
{
InvalidCredentialsOnNullUser(user);
FormsAuthentication.SetAuthCookie(user.Name, false);
}
/// <summary>
/// Log the user out
/// </summary>
public void LogOut()
{
FormsAuthentication.SignOut();
}
private static void InvalidCredentialsOnNullUser(LoginUser user)
{
if (user == null)
{
throw new InvalidCredentialException("That user doesn't exist or is not valid.");
}
}
// other methods....
}
The LoginUser class you see is information which is retrieved about a membership user. This is commonly done via a MembershipProvider but of course can be done other ways.
public class LoginUser
{
public string Name;
public Guid Key;
public string EmailAddress;
public bool IsApproved;
public bool IsLockedOut;
public DateTime CreationDate;
public DateTime? LastLoginDate;
public DateTime? LastPasswordChangedDate;
}
I'm not sure I understand the question correctly but if you're referring to a way of retrieving who the current user is without passing it through the URL (e.g. http://localhost/controller/action?username=RAMe0) then you can look at using Thread.CurrentPrincipal.Identity.Name or HttpContext.Current.User
There are subtle differences between the two however. Look here for more details.
Using FormsAuthentication you can store the Username in the User.Identity.Name property. Here's a simple example of what you probably are looking for. (Using the same SetAuth you're already using)
public ViewResult Index() {
return View(repository.GetUserProjects(this.User.Identity.Name));
}
This doesn't require you to pass the username in through a QueryString parameter.