Null reference on user identity - c#

I am new to writing a unit test case. I am getting error on User.Identity. I saw mocking is the resolution for that and I tried which is not working in my case. I have added my code
My Controller
public ActionResult CreateStage ( EnthiranStageViewModel enthiranStage )
{
if ( ModelState.IsValid )
{
Stage stage = enthiran.Insert_Stage(enthiranStage);
//logging Stage Creation
util.ApplicationLog(new ViewModel.Logs.ApplicationLogViewModel
{
GameCategorys = GameCategory.Enthiran,
Event = Events.EnthiranStageCreation,
SessionAttemptId = null,
UserId = User.Identity.GetUserId<int>( ),
OptionalParameter1 = enthiranStage.GameId,
OptionalParameter2 = stage.Id,
Description = "Enthiran stage created"
});
return RedirectToAction("Stages", new
{
id = stage.GameId
});
}
return View( );
}
and below is my test case
[TestMethod( )]
public void createStage ( )
{
EnthiranStageViewModel enthiranStage = new EnthiranStageViewModel
{
StageType=0,
TriggerBeginType = Akton.Areas.Challenge.Models.TriggerType.Manual,
TriggerEndType= Akton.Areas.Challenge.Models.TriggerType.Manual,
TimeLimit = new TimeSpan(9, 6, 13),
TriggerBeginTime= new DateTime(2016, 09, 3, 9, 6, 13),
TriggerEndTime= new DateTime(2016, 09, 3, 9, 6, 13),
StartValueType= Akton.Areas.Challenge.Models.StartValueType.Global,
StageDate= new DateTime(2016, 09, 3, 9, 6, 13),
Proforma=25,
GameId=19,
CreatedTime=new DateTime(2016, 09, 3, 9, 6, 13),
UpdatedTime= new DateTime(2016, 09, 3, 9, 6, 13),
StageName="Test",
};
EnthiranController controller = new EnthiranController( );
JsonResult actual = controller.CreateStage(enthiranStage) as JsonResult;
var result = actual.Data;
Assert.AreEqual("{ success = True }", result.ToString( ));
}
Here I have to pass the userId in the ViewModel.Logs.ApplicationLogViewModel, I have no idea how to do that.
How do I get the userId which is passing through applicationLogViewModel?

One solution is to change EnthiranController and pass, for example, IUserContext, something like this:
public interface IUserContext
{
public IPrincipal User {get;}
}
then pass that through constructor to the controller, and use that context to retrieve the user.
ctor EnthiranController(IUserContext userContext)
Then slightly change unit test to mock all these interfaces. Also instead of JsonResult you can use ActionResult or RedirectToRouteResult as it is shown in following example.
[TestMethod( )]
public void createStage ( )
{
//arrange
EnthiranStageViewModel enthiranStage = new EnthiranStageViewModel
{
StageType=0,
TriggerBeginType = Akton.Areas.Challenge.Models.TriggerType.Manual,
TriggerEndType= Akton.Areas.Challenge.Models.TriggerType.Manual,
TimeLimit = new TimeSpan(9, 6, 13),
TriggerBeginTime= new DateTime(2016, 09, 3, 9, 6, 13),
TriggerEndTime= new DateTime(2016, 09, 3, 9, 6, 13),
StartValueType= Akton.Areas.Challenge.Models.StartValueType.Global,
StageDate= new DateTime(2016, 09, 3, 9, 6, 13),
Proforma=25,
GameId=19,
CreatedTime=new DateTime(2016, 09, 3, 9, 6, 13),
UpdatedTime= new DateTime(2016, 09, 3, 9, 6, 13),
StageName="Test"
};
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
//TODO: setup mockPrincipal
Mock<IUserContext> mockUserContext = new Mock<IUserContext>();
mockUserContext.Setup(p => p.User).Returns(mockPrincipal.Object);
EnthiranController controller = new EnthiranController(mockUserContext.Object);
//act
var actual = controller.CreateStage(enthiranStage) as RedirectToRouteResult;
//assert
Assert.IsNotNull(actual);
}

Related

need to fetch A1 and A2 with minimum FirstTime and LastTime within all X1, X2 and X3. Looking for better way?

I have below data model, against each X1, X2 and X3 I have A1 and A2 with either identical FirstTime and LastTime or with different values.
var dataModel = new Dictionary<string, Dictionary<string, DataModel>>
{
{
"X1",
new Dictionary<string, DataModel>
{
{
"A1",
new DataModel { Name="A1", FirstTime = new DateTime(2020, 12, 15, 5, 30, 45), LastTime = new DateTime(2020, 12, 16, 5, 30, 45) }
},
{
"A2",
new DataModel { Name="A2", FirstTime = new DateTime(2020, 12, 15, 5, 30, 45), LastTime = new DateTime(2020, 12, 16, 5, 30, 45) }
}
}
},
{
"X2",
new Dictionary<string, DataModel>
{
{
"A1",
new DataModel { Name="A1", FirstTime = new DateTime(2020, 11, 15, 5, 30, 45), LastTime = new DateTime(2020, 11, 16, 5, 30, 45) }
},
{
"A2",
new DataModel { Name="A2", FirstTime = new DateTime(2020, 11, 15, 5, 30, 45), LastTime = new DateTime(2020, 11, 16, 5, 30, 45) }
}
}
},
{
"X3",
new Dictionary<string, DataModel>
{
{
"A1",
new DataModel { Name="A1", FirstTime = new DateTime(2020, 12, 15, 5, 30, 45), LastTime = new DateTime(2020, 12, 16, 5, 30, 45) }
},
{
"A2",
new DataModel { Name="A2", FirstTime = new DateTime(2020, 12, 15, 5, 30, 45), LastTime = new DateTime(2020, 12, 16, 5, 30, 45) }
}
}
}
};
I need to fetch A1 and A2 with minimum FirstTime and LastTime within all X1, X2 and X3. Here is my try, Is there other better way?
var lstDataModel = new List<DataModel>();
foreach (var dm in dataModel)
{
foreach (var val in dm.Value)
{
lstDataModel.Add(new DataModel
{
Name = val.Value.Name,
FirstTime = val.Value.FirstTime,
LastTime = val.Value.LastTime,
});
}
}
var query = lstDataModel
.GroupBy(cm => cm.Name)
.Select(g => new {
g.Key,
FirstTime = g.Min(cm => cm.FirstTime),
LastTime = g.Min(cm => cm.LastTime)
}).ToList();
Here is DataModel class,
public class DataModel
{
public string Name { get; set; }
public DateTime FirstTime { get; set; }
public DateTime LastTime { get; set; }
}
Assuming they all have the same keys (A1/A2):
var query = dataModel.Values
.SelectMany(d => d.Keys)
.Distinct()
.Select(key => new
{
Key = key,
FirstTime = dataModel.Values.Min(v => v[key].FirstTime),
LastTime = dataModel.Values.Min(v => v[key].LastTime),
})
.ToList();
Not sure if it's 'better' but it takes fewer lines of code

How to convert a list to a jagged array in c#?

I am calling a third party API that expect a jagged array as input but I need to build this list dynamically.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var slots = new DateTime[][]
{
new DateTime[] {new DateTime(2020, 2, 14), new DateTime(2020, 2, 20)},
new DateTime[] {new DateTime(2020, 2, 15), new DateTime(2020, 2, 23)},
new DateTime[] {new DateTime(2020, 2, 16), new DateTime(2020, 2, 24)}
};
DateTime[][] slots2;
List<DateTime> appointments=new List<DateTime>();
appointments.Add(new DateTime(2020, 2, 14));
appointments.Add(new DateTime(2020, 2, 20));
slots2 = appointments.ToArray();
}
}
}
in the above code when I try to initialize the jagged array slots with datetime objects it works fine but when I try to use appointments list I get an error with slots2. How to initialize slot2 with a list of date time to populate slots2?
You need to initialise it first.
// create 1 element in the first dimension
var slots2 = new DateTime[1][];
var appointments = new List<DateTime>
{
new DateTime(2020, 2, 14),
new DateTime(2020, 2, 20)
};
// add the second dimension to the first element you created
slots2[0] = appointments.ToArray();
or
var slots2 = new[]
{
new[]
{
new DateTime(2020, 2, 14),
new DateTime(2020, 2, 20)
}
};
Edit
Why not just use List<List<DateTime>> and project them into arrays
var appointments = new List<List<DateTime>>
{
new List<DateTime>
{
new DateTime(2020, 2, 14),
new DateTime(2020, 2, 20)
}
};
Then you can add more
appointments.Add(new List<DateTime>
{
new DateTime(2020, 2, 14),
new DateTime(2020, 2, 20)
});
var slots2 = appointments.Select(x => x.ToArray()).ToArray();

And operator in MongoDB to perform query with multi-filters using the official .NET driver

I am using MongoDB 3.2 and I want to make a query from C# using the official .NET driver (2.6)
Use Robomongo to perform the search, and the correct query is:
db.getCollection('collection1').find({ $and: [ { type: "ws128" }, { tsend: { $gte: ISODate("2018-05-11T14:39:33.000Z"), $lt: ISODate("2018-05-11T14:39:40.000Z") } } ] })
I want to find all the documents that have the key type = ws128 and that the variable tsend is between the two dates that are shown in the query.
In C #, I have the filters defined as shown below but I do not know how to do the query:
DateTime datetimestart = new DateTime(2018, 5, 11, 14, 39, 33);
DateTime datetimeend = new DateTime(2018, 5, 11, 14, 39, 40);
var filter1 = Builders<BsonDocument>.Filter.Eq("type", "ws128");
var filter2 = Builders<BsonDocument>.Filter.Gte("tsend", datetimeend);
var filter3 = Builders<BsonDocument>.Filter.Lt("tsend", datetimestart);
With a single filter, the search performed without problems as shown below, but I do not know how to include the 3 filters.
var cursor = collection.Find(filter1).ToCursor();
Can someone guide me to continue?
Thank you!
regards,
You can simply do:
collection.Find(filter1 & filter2 & filter3)
or alternatively:
collection.Find(Builders<BsonDocument>.Filter.And(filter1, filter2, filter3))
use a single &
DateTime datetimestart = new DateTime(2018, 5, 11, 14, 39, 33);
DateTime datetimeend = new DateTime(2018, 5, 11, 14, 39, 40);
var filter1 = Builders<BsonDocument>.Filter.Eq("type", "ws128");
var filter2 = Builders<BsonDocument>.Filter.Gte("tsend", datetimeend);
var filter3 = Builders<BsonDocument>.Filter.Lt("tsend", datetimestart);
var andFilter = filter1 & filter2 & filter3;
var cursor = collection.Find(andFilter).ToCursor();
I would probably write that code a little differently. I find it easier to read and write:
DateTime datetimestart = new DateTime(2018, 5, 11, 14, 39, 33);
DateTime datetimeend = new DateTime(2018, 5, 11, 14, 39, 40);
var builder = Builders<BsonDocument>.Filter;
var filter1 = builder.Eq("type", "ws128");
var filter2 = builder.Gte("tsend", datetimeend);
var filter3 = builder.Lt("tsend", datetimestart);
var cursor = collection.Find(filter1 & filter2 & filter3).ToCursor();

C# datetime array

I have two arrays, array1 has datetime data count by minute from 8am to 2pm and array2 has datetime data count by hour from same date 8am to 1pm.
I want to output the index number of two array that has same datetime.hour. and it should matchup the last available index number of array2 for all of the datetime data from array1 that later than array2.
for example if I have two datetime array like this:
DateTime[] dateTimes1 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 15, 0),
new DateTime(2010, 10, 1, 8, 30, 1),
new DateTime(2010, 10, 1, 8, 45, 2),
new DateTime(2010, 10, 1, 9, 15, 3),
new DateTime(2010, 10, 1, 9, 30, 4),
new DateTime(2010, 10, 1, 9, 45, 5),
new DateTime(2010, 10, 1, 10, 15, 6),
new DateTime(2010, 10, 1, 10, 30, 7),
new DateTime(2010, 10, 1, 10, 45, 8),
new DateTime(2010, 10, 1, 11, 15, 9),
new DateTime(2010, 10, 1, 11, 30, 10),
new DateTime(2010, 10, 1, 11, 45, 11),
new DateTime(2010, 10, 1, 12, 15, 12),
new DateTime(2010, 10, 1, 12, 30, 13),
new DateTime(2010, 10, 1, 12, 45, 14),
new DateTime(2010, 10, 1, 13, 15, 15),
new DateTime(2010, 10, 1, 13, 30, 16),
new DateTime(2010, 10, 1, 13, 45, 17),
new DateTime(2010, 10, 1, 14, 15, 18),
new DateTime(2010, 10, 1, 14, 30, 19),
new DateTime(2010, 10, 1, 14, 45, 20),
};
DateTime[] dateTimes2 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 0, 0),
new DateTime(2010, 10, 1, 9, 0, 1),
new DateTime(2010, 10, 1, 10, 0, 2),
new DateTime(2010, 10, 1, 11, 0, 3),
new DateTime(2010, 10, 1, 12, 0, 4),
new DateTime(2010, 10, 1, 13, 0, 5),
};
it should gives me the output:
0, 0
1, 0
2, 0
3, 1
4, 1
5, 1
6, 2
7, 2
8, 2
9, 3
10, 3
11, 3
12, 4
13, 4
14, 4
15, 5
16, 5
17, 5
18, 5
19, 5
20, 5
This is what I have tried:
int i = 0;
int j = 0;
while (i < dateTimes1.Length && j < dateTimes2.Length)
{
if (dateTimes1[i].Date == dateTimes2[j].Date && dateTimes1[i].Hour == dateTimes2[j].Hour)
{
list.Add(i);
list2.Add(j);
i++;
}
else if (dateTimes1[i] < dateTimes2[j])
{
i++;
}
else if (dateTimes1[i] > dateTimes2[j])
{
j++;
}
}
for (int k = 0; k < list.Count; k++)
{
Console.WriteLine(list[k] + " , " + list2[k];
}
but it won't output the index number after 1pm.
Your two lists are not the same length. In your while statement you are trying to iterate two different length lists at the same time.
If I understand your requirements properly you should be doing something like this by using an inner loop:
DateTime[] dateTimes1 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 15, 0),
new DateTime(2010, 10, 1, 8, 30, 1),
new DateTime(2010, 10, 1, 8, 45, 2),
new DateTime(2010, 10, 1, 9, 15, 3),
new DateTime(2010, 10, 1, 9, 30, 4),
new DateTime(2010, 10, 1, 9, 45, 5),
new DateTime(2010, 10, 1, 10, 15, 6),
new DateTime(2010, 10, 1, 10, 30, 7),
new DateTime(2010, 10, 1, 10, 45, 8),
new DateTime(2010, 10, 1, 11, 15, 9),
new DateTime(2010, 10, 1, 11, 30, 10),
new DateTime(2010, 10, 1, 11, 45, 11),
new DateTime(2010, 10, 1, 12, 15, 12),
new DateTime(2010, 10, 1, 12, 30, 13),
new DateTime(2010, 10, 1, 12, 45, 14),
new DateTime(2010, 10, 1, 13, 15, 15),
new DateTime(2010, 10, 1, 13, 30, 16),
new DateTime(2010, 10, 1, 13, 45, 17),
new DateTime(2010, 10, 1, 14, 15, 18),
new DateTime(2010, 10, 1, 14, 30, 19),
new DateTime(2010, 10, 1, 14, 45, 20),
};
DateTime[] dateTimes2 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 0, 0),
new DateTime(2010, 10, 1, 9, 0, 1),
new DateTime(2010, 10, 1, 10, 0, 2),
new DateTime(2010, 10, 1, 11, 0, 3),
new DateTime(2010, 10, 1, 12, 0, 4),
new DateTime(2010, 10, 1, 13, 0, 5),
};
int i = 0;
while (i < dateTimes1.Length)
{
int j = 0;
while (j < dateTimes2.Length))
{
if (dateTimes1[i].Date == dateTimes2[j].Date && dateTimes1[i].Hour == dateTimes2[j].Hour)
{
list.Add(i);
list2.Add(j);
i++;
}
else if (dateTimes1[i] < dateTimes2[j])
{
i++;
}
else if (dateTimes1[i] > dateTimes2[j])
{
j++;
}
}
}
for (int k = 0; k < list.Count; k++)
{
Console.WriteLine(list[k] + " , " + list2[k];
}
Here's a pretty basic method using Array.FindIndex and foreach:
EDIT: Updated this answer to handle the "matchup the last available index number of array2 for all of the datetime data from array1 that later than array2." issue.
foreach (DateTime dt in dateTimes1)
{
int currentHour = dt.Hour;
int lastHour = dateTimes2[dateTimes2.GetUpperBound(0)].Hour; //GetUpperBound(0) is the last index
int dt1index = Array.FindIndex(dateTimes1, a => a == dt); //get the index of the current item in dateTimes1
int dt2index = Array.FindIndex(dateTimes2, x => x.Hour == currentHour); //get the index of the item in dateTimes2 matching dateTimes1 hour field
if (currentHour > lastHour)
{
Console.WriteLine("{0}, {1}", dt1index, dateTimes2.GetUpperBound(0));
}
else
{
Console.WriteLine("{0}, {1}", dt1index, dt2index);
}
}
This simply looks at each of the values in dateTimes1 and dateTimes2 and returns the first match it finds (very similar to your loop).
To determine dt1index, we look through dateTimes1 and return the first match where a => a == dt (a is just the predicate, representing the "current" value in dateTimes1 - think of i = 0,1,2,etc in a regular loop ).
Similarly, to determine dt2index, we look for the first match on x => x.Hour == dt.Hour -- that is, where the "current" dt's hour field matches the hour field in dateTimes2.
In both cases, the first match is returned - if no matches are found, -1 is returned.
When we go to write to the console, we check if currentHour is greater than the last hour in dateTimes2 if so, we just write the current index of dateTimes1 and the last index of dateTimes2. Otherwise, we write the current index of dateTimes1 and the index where the hour matches on dateTimes2.
Using Linq:
var hour = new TimeSpan(1, 0, 0);
var dt2MaxValue = dateTimes2.Max();
for (int i = 0; i < dateTimes1.Length; i++)
{
var output = string.Format("{0}, {1}",
i,
dateTimes2
.Select((o, index) => new { index = index, value = o })
.Where(dt2 => (dateTimes1[i] - dt2.value) < hour
|| dt2.value == dt2MaxValue)
.Select(dt2 => dt2.index)
.FirstOrDefault());
Console.WriteLine(output);
}
What the above Linq statement does:
The first Select uses that method's overload which also passes the index of the item. This simply allows that info to cascade through. It uses an anonymous object with both index and the collection item being the index and value properties, respectively.
The Where clause queries the collection of these anonymous objects and compares their value with dateTime1[i]. It gets the one where value is less than dateTime1[i] but not by more than 1 hour, OR if it is the maximum value in the whole collection.
The second Select simply gets the indexes of the items that Where filtered through.
And FirstOrDefault returns just that (ie, the first or default, which is the index of the item selected or 0 if no item was selected).

LINQ Solution for Multiple Resolves

I have an array of MyClass, which can be simplified as follow:
public class MyClass {
public int Id;
public string Origin;
public int Points;
public DateTime RequestTime;
public MyClass(int id, string origin, int points, DateTime requestTime) {
Id = id;
Origin = origin;
Points = points;
RequestTime = requestTime;
}
}
Now, in the Array, without any errors from the user side or throughout the input process, there cannot be MyClass instance with identical Id and Origin.
However, if there be any, I should resolve it. And here are the resolving rules:
Firstly by Points - that is, to take one among the duplicates which has the highest Points
But if the Points are the same, I have to further resolve it by using RequestTime - the latest will be taken.
And if, there is no difference in RequestTime, then I can take one of the duplicates arbitrarily.
Here is the sample data input I have:
MyClass[] myarr = new MyClass[] {
new MyClass(1, "Ware House 1", 5, new DateTime(2016, 1, 26, 14, 0, 0)), //[0]
new MyClass(1, "Ware House 1", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[1] //higher points
new MyClass(1, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[2]
new MyClass(1, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 1, 0)), //[3] //later time
new MyClass(1, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[4]
new MyClass(2, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[5] //higher points
new MyClass(2, "Ware House 2", 5, new DateTime(2016, 1, 26, 14, 1, 0)), //[6] //later time but less points
new MyClass(3, "Ware House 1", 6, new DateTime(2016, 1, 26, 14, 0, 0)), //[7] //triplet, pick any
new MyClass(3, "Ware House 1", 6, new DateTime(2016, 1, 26, 14, 0, 0)), //[8] //triplet, pick any
new MyClass(3, "Ware House 1", 6, new DateTime(2016, 1, 26, 14, 0, 0)) //[9] //triplet, pick any
};
The final result should be [1], [3], [5], + any of [7]/[8]/[9]
I want to implement LINQ solution for it, but stuck. I do not know how make query it at once.
Any idea?
Group by {Id, Origin} and take the first one from each group when ordered by Points and RequestTime:
var query = from x in myarr
group x by new {x.Id, x.Origin}
into g
select (
from z in g
orderby z.Points descending, z.RequestTime descending
select z).First();
In method syntax, this is:
var query =
myarr.GroupBy(x => new {x.Id, x.Origin})
.Select(g => g.OrderByDescending(z => z.Points)
.ThenByDescending(z => z.RequestTime)
.First());
Try following:
myarr.OrderBy(m=> m.Points).ToList();
or
myarr.OrderBy(m=> m.Points).Orderby(m=> m.RequestTime);

Categories