Property not loading straightaway EF6 - c#

I have a Request class containing a property CreatedBy of the type ApplicationUser.
I then need to do some authorization to see if the request is accessible by the current user, like so:
public bool HasAccessToRequest(Request req)
{
var user = GetCurrentUser();
if (req == null)
{
return false;
}
if (req.CreatedBy.Department.Managers.Any(x => x.Id == user.Id))
{
return true;
}
return false;
}
Where GetCurrentUser() just get's the currently logged in user as an object.
The issue is, when I do this I get an error:
“Object reference not set to an instance of an object”
This is verifiable by stepping through this block of code and I notice that when breakpointing, CreatedBy is indeed not loaded. Then I look to my db table and there is a valid value there, so I try again but this time waiting for about 5 seconds and then it magically appears in the req parameter upon hovering over.
I'm not using any sort of async methods and I have this same method in a different controller which is working totally fine. Any pointers on what it could be? As far as I know there is no other code that is running before hand that I need to wait for, I can just see that this is taking a while to load and without setting a breakpoint and waiting I get the above error.
First this happens:
Then after waiting for 2-4 seconds this happens:

Looks like I had lazy loading disabled for CreatedBy so making it:
public virtual ApplicationUser CreatedBy { get; set; }
Seemed to fix the issue. This is a little bit confusing because I'm more than half way through the development of this project and this field never needed to be virtualised before and worked completely fine, and I'm not sure if it could cause potential problems later on.

Related

EF Core - Update Entity in Controller after it was modified in Method | How to apply manual Changes above automatic Workflows?

I have an action "Save". This action loads an "Order" Entity from the DB and applies possible changes by the User. Every time this action is executed it also runs "UpdateOrderStates" and that´s where the problems begin.
When I use this Method, my changes in the action itself will be overwritten in the Method and I cannot change them anymore.
public IActionResult Save(MyViewModel model){
var order = context.Orders....
if(model.MyState !=null && model.MyState !=order.MyState){
order.MyState=model.MyState;
}
//more stuff....
await workflow.UpdateOrderStates(model.orderId);
//context.Update(order);
context.Entry(order).State = EntityState.Modified;
await context.SaveChangesAsync();
}
public void UpdateOrderStates(int orderId){
var order = context.Orders....
var subOrders = order.SubOrders;
var subOrdersStateAll = subOrders.All(x=>x.MyState=="DONE");
//.....
if(subOrdersStateAll) order.MyState ="DONE"; //There are way more states and options for each state
context.Update(order);
await context.SaveChangesAsync();
}
When I follow this I can see that the order gets updated in the if and then after the "workflow.UpdateOrderStates()" is done, the "MyState" in order will be reset to the one in the Method. I thought that I can fix it with "EntityState.Modified", but apparently not.
1.) What do I have to do to take the object I have in my action and not the data which has been updated by the Method?
2.) Do you perhaps have an idea how to make this so that the manual and automatic Changes work together? ie.: This only would have the correct State after the first save, but when I save it a second time and I do not change anything in MyState (only the description) then the State will be overwritten by the Method, although I would like to keep the State, the User set. And this "UpdateOrderStates" is being used in multiple places....

entity framework (MSSQL 2016) + xUnit test - tries to update "GENERATE ALWAYS" column SysStartTime

I am having a strange problem:
I have a quite simple Login(string user, string pass) method for user login which needs to save last login date of that user:
using (MyDbContext dbContext = new MyDbContext())
{
var dbUser = dbContext.IdentityUserLogins.SingleOrDefault(u =>
u.LoginProvider == login && u.ProviderKey == password);
if (dbUser != null)
{
dbUser.LastLoginDate = DateTime.Now;
dbContext.Entry(dbUser).State = System.Data.Entity.EntityState.Modified;
dbContext.SaveChanges();
var id = Convert.ToInt32(dbUser.UserId);
/*other stuff*/
}
}
When I run this from a regular debug, everything works fine. The user I enter is found, his LastLoginDate is updated successfully and its Autogenerated SysStartTime is updated automatically at SaveChanges()
But when I run this method from an xUnit test, it behaves strange.
The test is simple, like this:
[Fact]
[Trait("Category", "MyCategory")]
public void LoginTest()
{
string user = /*user name*/
string pass = /*get password hash*/
UserModel user = handler.Login(user, pass);
Assert.NotNull(user);
}
It simply calls that method.
The problem occurs on SaveChanges() call, an exception is thrown:
Cannot update GENERATED ALWAYS columns in table 'AppIdentityUserLogin'
Our tables use these columns like SysStartTime, SysEndTime and RowVersion, but there are no problems with Entity Framework knowing, how to handle them, this is the only exception - this xUnit test.
The problem is most likely in the dbContext.Entry(dbUser)... line, because when I comment it out, the test passes normally. I even think it is not needed there, because without it everything updates the same in regular debug.
EDIT: Both - xUnit tests and regular debug are using the same ConnectionString.
What could cause this strange behavior? I tried to find some pre-run config, some differences between accessing this method as a test debugger and as a regular debugger, but couldn't find anything.
Solved it.
Credit goes to Matt Ruwe and his solution to the Temporal table problem he had.
I simply had to tell EF, not to try to overwrite the Generated columns.
In my case I had to set the _namesToIgnore to "SysStartTime" and "SysEndTime" and then put this line in my BaseTest constructor
System.Data.Entity.Infrastructure.Interception.DbInterception.Add(new EF.TemporalTableCommandTreeInterceptor());
Now everything inserts and updates normally even from xUnit test debug.

How to solve Stored XSS issue reported by Checkmarx

Codebase I am working on has been analyzed by Checkmarx, and it came back with a report containing a "Stored XSS" issue. The issue states:
Method GetHomepageFilterByLocale HomepageRepo.cs gets data from the database, for the Select element. This element’s value then flows through the code without being properly filtered or encoded and is eventually displayed to the user in method GetProductsByFilterType HomepageController.cs. This may enable a Stored Cross-Site-Scripting attack.
Is there a standard recommended way to resolve this issue?
Please see below code snippets for the both mentioned methods.
HomepageRepo.cs
public HomepageFilter GetHomepageFilterByLocale(int localeId)
{
return _context.HomepageFilter.SingleOrDefault(x => x.LocaleId == localeId);
}
HomepageController.cs
GetHomepageViewModel() method is where the repository method is called.
[HttpGet]
public ActionResult GetProductsByFilterType(int locale, string filterType)
{
HomepageViewModel model = GetHomepageViewModel(locale, filterType);
if (model?.Products != null)
{
model.Products.ForEach(p => p.Name = HttpUtility.HtmlEncode(p.Name));
model.Products.ForEach(p => p.ImageUrl = HttpUtility.HtmlAttributeEncode(p.ImageUrl));
}
return Json(model, JsonRequestBehavior.AllowGet);
}
You should look at the vulnerability flow (to the right of the screen when you view the vulnerability) and see what objects are involved in this vulnerability.
You can also click on the little question mark sign ('?') on the right of the vulnerability name. it should tell you how to resolve it.
Finally, if you are still facing issues, you can click on the query viewer and preview what the query looks for exactly.
Now: from my own experience, xss vulnerabilities are easily fixed with HttpUtility.HtmlEncode method.
I'm thinking something like:
HttpUtility.HtmlEncode(_context.HomepageFilter.SingleOrDefault(x => x.LocaleId == localeId));

Retrieving Records and Saving to a Database in a single C# Web Service

Hi i am trying to combine a C# webservice in azure with a get and a post at the same time, the idea is to get the details of a CD by the uniqueCDcode and the webservice outputs just the json information AND the uniqueCDcode needs to be stored in a different table CDClicked to i get a list of all the clickedCD's so i am able to take the last 50 as for trending etc. but don't really seem to get it to work. This is what i have so far
//// WS# 00002 GET THE ALBUM DETAILS
[Route("api/Music/Album/{uniqueCDcode}")]
public HttpResponseMessage GetAlbum(int uniqueCDcode)
{
return Request.CreateResponse(HttpStatusCode.OK,
new { AlbumMusic = db.Music
.Where(am => am.uniqueCDcode == uniqueCDcode);
db.CDClicked.Add(uniqueCDcode);
}
You need to retrieve your record/do the save, then return the response. The Add() method call to dbContext (second part) isn't working because the return statement is returning a value first, and then stopping the execution of your service, so it never gets to the second part. Your logic needs to be done before the return statement.
For example:
[Route("api/Music/Album/{uniqueCDcode}")]
public HttpResponseMessage GetAlbum(int uniqueCDcode)
{
db.CDClicked.Add(uniqueCDcode);
return Request.CreateResponse(HttpStatusCode.OK,
new { AlbumMusic = db.Music
.Where(am => am.uniqueCDcode == uniqueCDcode )});
}
You also had some formatting issues in the code. Your braces and parens didn't match up (at least in the code that you pasted into SO.) I corrected in my answer below.
Note: I can't test the code at the moment due to hurricane-related issues, but this is the general concept to get you going again.

SimpleMembershipProvider intermittently returning wrong user

I am administrator of a small practice project web application, AngularJS front-end pulling its back-end data from a C#/.NET WebAPI, and I'm handling security using the SimpleMembershipProvider.
I suspect that the way I implemented said security is not the best (I'm told ASP.NET Identity is now the way to go?) but that's another question altogether.
The issue that I'm very bewilderingly running into is that I get occasional reports that on a given page load to display a particular user's data, it returns somebody else's. Reloading the page fixes the issue (evidently) and I haven't been able to duplicate the scenario myself, or figure out anything particularly consistent in the users to which this happens.
None of the information being displayed is at all sensitive in nature (the app's just a friendly front end for an already public third-party API) so I'm not in panic mode about this, but I am both concerned and confused and want it fixed.
Here is what one of my API controller endpoints looks like:
[Authorize]
public class UserController : ApiController
{
private static int _userId;
private readonly IUserProfileRepository _userProfileRepository;
public UserController()
{
_userProfileRepository = new UserProfileRepository(new DatabaseContext());
_userId = WebSecurity.GetUserId(User.Identity.Name);
}
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(_userId).ToDto();
}
}
Any feedback on where I might be going wrong here or what might be causing the intermittant inconsistency would be very much appreciated. (Laughter also acceptable if the way I handled this is just really bad. :P )
Static class fields are shared by all instances/threads of the same AppDomain (in your case - process). Different http requests are processed by threads running in parallel. Any two threads running [almost] at the same time may (will) change the value of _userId. You are assigning _userId in the constructor of your controller, and a new instance of this controller is created for each http request that is to be responded to by UserController. Therefore, this assignment will happen multiple times.
You will have hard time replicating this problem, since you are a single user testing the code, hence there are no overlapping request threads.
Remove static specifier from the _userId field declaration of the controller class.
Note: make sure that DatabaseContext is disposed of. One place that can be used for this is the overriden Controller.Dispose.
Change the Get to retrieve the user id rather than from a static variable:
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(WebSecurity.GetUserId(User.Identity.Name)).ToDto();
}

Categories