Get object on Entity Framework Core interceptor before insert command - orm

For some reason i want to get object before it was inserted on Ef Core Intreceptor , for ex when i want
var newOrder = new Order { CustomerID = 3, EmployeeID = 4, OrderDate = DateTime.Now };
_myContext.Orders.Add(newOrder);
_myContext.SaveChanges();
i try to get newOrder on ReaderExecuting method of Interceptor so i override this method :
public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
{
return base.ReaderExecuting(command, eventData, result);
}
this method is called, so how can i get newOrder on above method?
I know in NHibernate we can doing this like this:
public bool OnPreInsert(PreInsertEvent #event)
{
//some other codes
}
i can get the the object by #event.Entity, but in Ef Core 3 is there any way to do like this?

Related

How to handle unknown parameters in ASP.NET Core Actions

How to handle unknown parameters in ASP.NET Core? When I use [FromQuery] it just ignores the unknown parameters, but ideally it should return 400 if the parameter is unknown so the caller knows it needs to fix the parameters?
Example: GetRecords tries to use any StartDate or EndDate from query string, use default value if they are not specified.
But if a query like ?StartTime=2021/2/15&EndTime=2021/2/16, the code actually will return all records from DB as it treats like no parameters passed. Ideally it should throw an error to let caller know the parameter names are invalid.
class RecordQuery
{
public RecordQuery()
{
StartDate = DateTime.MinValue;
EndDateTime = DateTime.Now;
}
//...
}
class Controller
{
public async Task<ActionResult<RecordsResult>> GetRecords([FromQuery] RecordQuery query)
{
// query db where date < query.EndDateTime && date > query.StartDateTime;
}
}
When I use [FromQuery] it just ignores the unknown parameters
Actually, this is the default behavior of the querystring parameters. But you could return an Invalid Request status, so that the client knows that what it's trying to do isn't valid.
To implement it, you can use the ActionFilter, get both the action parameters and request query string queryParameters and make a judgement. Codes like below:
public class QueryActionFilter<T> : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
var model = context.ActionArguments.Values.OfType<T>().Single();
var modelProperties = model.GetType().GetProperties();
var queryParameters = context.HttpContext.Request.Query;
if (!queryParameters.Select(q => q.Key).All(queryParameter => modelProperties.Any(p => p.Name == queryParameter)))
{
context.Result = new BadRequestObjectResult("Querystring does not match");
}
}
}
Then in controller
[TypeFilter(typeof(QueryActionFilter<RecordQuery>))]
public async Task<ActionResult<RecordsResult>> GetRecords([FromQuery] RecordQuery query)
{
// query db where date < query.EndDateTime && date > query.StartDateTime;
}
You can see example https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-5.0&tabs=visual-studio#the-puttodoitem-method
if(StartDate == null){
return BadRequest();
}
Let's do the same thing with another input parameter(s) (query conditions)
If you want validate input parameter(s), use [Required] for model of [FromQuery], see https://stackoverflow.com/a/19279419/3728901 . In your case, it is model RecordQuery .

FakeItEasy ControllerTest HttpGet Calls

I want to start using FakeItEasy for testing queries.
The tests I want to write should check if entities are returned on HttpGet calls (get all and get by Id)
The Controller:
public class ToDoController : ControllerBase
{
private readonly IMediator _mediator;
public ToDoController(IMediator mediator) =>
_mediator = mediator;
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(typeof(IEnumerable<ToDoItem>), (int)HttpStatusCode.OK)]
public async Task<ActionResult<IEnumerable<ToDoItem>>> Get()
{
var result = await _mediator.Send(new ToDoItemsQuery(new
AllToDoItems())).ConfigureAwait(false);
if (result != null && result.Any())
{
return result.ToList();
}
throw new InvalidOperationException("TODO: error handling");
}
[HttpGet]
[Route("{id}")]
[Produces("application/json")]
[ProducesResponseType(typeof(ToDoItem), (int)HttpStatusCode.OK)]
public async Task<ActionResult<ToDoItem>> GetById(int itemId)
{
var result = await _mediator
.Send(new ToDoItemsQuery(new ToDoItemById(itemId)))
.ConfigureAwait(false);
if (result != null && result.Any())
{
return result.FirstOrDefault();
}
throw new InvalidOperationException("TODO: error handling");
}
}
}
The TestClass:
public class ToDoItemControllerTests : ControllerTestBase
{
private IMediator _mediator;
private ToDoController _sut;
public ToDoItemControllerTests()
{
_mediator = A.Fake<IMediator>();
_sut = new ToDoController(_mediator);
}
[TestMethod]
public async Task GetAllItemsAsync_SuccessTest()
{
A.CallTo(() => _mediator.Send(A<AllToDoItems>._,
A<CancellationToken>._)).Returns(A.CollectionOfFake<ToDoItem>(10));
var result = await _sut.Get();
Assert.IsNotNull(result);
A.CallTo(() => _mediator).MustHaveHappened();
}
[TestMethod]
public async Task GetItemByIdAsync_SuccessTest()
{
// Arrange
int itemId = 2;
var commandResult =
new List<ToDoItem>
{
new ToDoItem
{
Id = itemId
};
}
A.CallTo(() => MediatR.Send(A<ToDoItemById>._, A<CancellationToken>._)).Returns(commandResult);
// Act
var result = await _sut.GetById(itemId);
// Assert
Assert.IsNotNull(result);
A.CallTo(() => MediatR.Send(A<ToDoItemById>._, A<CancellationToken>._)).MustHaveHappened();
}
}
So in the first test I set up A.CallTo the interface IMediatR to return 10 ToDoItems.
During debug I see the _sut.Get() enter the controller, entering the correct method/api call.
The _mediator.Send() in the controller returns a Fake IEnumerable (not the 10 items i set up in the first Call.To in the testmethod, but an enumeration that yields no results).
Because of the result.Any() being false, the controller throws an InvalidOperationException
And I cannot even Assert the result.IsNotNull()
The second test I want to Test If 1 item is returned upon calling the API.
I set up (a) an itemId of type int for parameter,
(b) A mocked(?) List with 1 Item from the setup with the itemId and
(c) a call to the mediatR should return the mocked Listfrom (b)
I make the call from the test, in debug I see the call await _mediator.Sent() returning
A Fake Ienumerable of ToDoItem, result is not null, but because result.Any() is false,
the item doesn't get returned, and I get another InvalidOperationException
I feel like I'm missing something in the setup of the tests..
A Fake database Interface?
I don't want to chance my controller and make the if less restrictive, just so my test would pass
EDIT:
Even if I change the if condition to removing the Any condition
and I see the test entering the controller, returning "First Or Default" of the result,
The test fails on A Call To Must Have Happened.
Expected to find it once or more but no calls were made to the fake object.
This I really don't get, i actually see him making the call?!
I've browsed GitHub to find examples but the closest I found was Entities with methods, with those methods being defined in an interface. This is not the case here
Seeing as the official documentation doesn't make me any wiser I turn to SO <3
Thanks in advance!
In the first test, you configure the call to Send with an argument of type AllToDoItems. But in the controller, you actually call Send with a TodoItemsQuery. So the call doesn't match, and the default (unconfigured) behavior, which is to return a fake IEnumerable, applies. You need to configure the call like this:
A.CallTo(() => _mediator.Send(A<TodoItemsQuery>._,
A<CancellationToken>._)).Returns(A.CollectionOfFake<ToDoItem>(10));
In the second test, the problem is the same, with ToDoItemById instead of AllToDoItems

HttpContext.Current null when making a function Asynchronous in MVC4

I am currently working on MVC4 in VS2010-SP1. I made one of the function in
the controller class Asynchronous. As part of that I made the controller class
derived from AsyncController and added the below two methods ( see code section 1 and
2 below). one method ending with Async(See Code Section 1 ) and another method ending
with Completed ( See Code Section 2 ). The problem is in the model class I am trying
to access my webservice with credentials from HttpContext ( See Code below 3 ). The
context is going null when making an asynchronous call. ie, In the new thread
httpcontext is not available. How to pass the context from main thread to new threads
created.
Code Section 1
public void SendPlotDataNewAsync(string fromDate, string toDate, string item)
{
AsyncManager.OutstandingOperations.Increment();
var highChartModel = new HighChartViewModel();
Task.Factory.StartNew(() =>
{
AsyncManager.Parameters["dataPlot"] =
highChartModel.GetGraphPlotPointsNew(fromDate, toDate, item);
AsyncManager.OutstandingOperations.Decrement();
});
}
Code Section 2
public JsonResult SendPlotDataNewCompleted(Dictionary<string, List<ChartData>>
dataPlot)
{
return Json(new { Data = dataPlot });
}
Code Section 3
public List<MeterReportData> GetMeterDataPointReading(MeterReadingRequestDto
meterPlotData)
{
var client = WcfClient.OpenWebServiceConnection<ReportReadingClient,
IReportReading>(null, (string)HttpContext.Current.Session["WebserviceCredentials"] ??
string.Empty);
try
{
return
ReadReportMapper.MeterReportReadMap(client.GetMeterDataPointReading(meterPlotData));
}
catch (Exception ex)
{
Log.Error("MetaData Exception:{0},{1},{2},{3}",
ex.GetType().ToString(), ex.Message, (ex.InnerException != null) ?
ex.InnerException.Message : String.Empty, " ");
throw;
}
finally
{
WcfClient.CloseWebServiceConnection<ReportReadingClient,
IReportReading> (client);
}
}
HttpContext.Current is null because your task is executed on a pool thread without AspNetSynchronizationContext synchronization context.
Use TaskScheduler.FromCurrentSynchronizationContext():
Task.Factory.StartNew(() =>
{
AsyncManager.Parameters["dataPlot"] =
highChartModel.GetGraphPlotPointsNew(fromDate, toDate, item);
AsyncManager.OutstandingOperations.Decrement();
},
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());

How to access property of anonymous type?

Considering this IronPython script
def SensorEvent(d):
print d
print d.Message
... how do I access properties of d?
First line of the SensorEvent method successfully prints
{ Message = blah blubb }
however second line throws an exception:
'<>f_anonymousType[str]' object has no attribute 'Message'
Explanation
d is an instance of an anonymous type provided by an invoke from a C# method. I'm invoking it like this:
public static async void ExecutePyFunc(string name, dynamic data)
{
try
{
var f = strategyScope.GetVariable<Action<object>>(name);
if (f != null)
{
await Task.Run(() => f((object)data));
}
}
catch (Exception x)
{
StaticLog("[Callback Exception] Fehler beim Ausführen einer Python Funktion: {0}", x.Message);
}
}
d is a dictionary. Access it like so:
d['Message']
My solution using DynamicObject: I've introduced a class that converts an anonymous type into a known type by copying its properties via reflection (I don't need anything but the properties but it could probably be enhanced for use with fields, methods, functions as well).
Here's what I've come up with:
public class IronPythonKnownType : DynamicObject
{
public IronPythonKnownType(dynamic obj)
{
var properties = obj.GetType().GetProperties();
foreach (PropertyInfo prop in properties)
{
var val = prop.GetValue(obj);
this.Set(prop.Name, val);
}
}
private Dictionary<string, object> _dict = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_dict.ContainsKey(binder.Name))
{
result = _dict[binder.Name];
return true;
}
return base.TryGetMember(binder, out result);
}
private void Set(string name, object value)
{
_dict[name] = value;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_dict[binder.Name] = value;
return true;
}
}
which effectively converts the anonymous object into something IronPython can handle.
Now I can do that:
def Blubb(a):
print a.Message
without getting the mentioned exception.

Duck type testing with C# 4 for dynamic objects

I'm wanting to have a simple duck typing example in C# using dynamic objects. It would seem to me, that a dynamic object should have HasValue/HasProperty/HasMethod methods with a single string parameter for the name of the value, property, or method you are looking for before trying to run against it. I'm trying to avoid try/catch blocks, and deeper reflection if possible. It just seems to be a common practice for duck typing in dynamic languages (JS, Ruby, Python etc.) that is to test for a property/method before trying to use it, then falling back to a default, or throwing a controlled exception. The example below is basically what I want to accomplish.
If the methods described above don't exist, does anyone have premade extension methods for dynamic that will do this?
Example: In JavaScript I can test for a method on an object fairly easily.
//JavaScript
function quack(duck) {
if (duck && typeof duck.quack === "function") {
return duck.quack();
}
return null; //nothing to return, not a duck
}
How would I do the same in C#?
//C# 4
dynamic Quack(dynamic duck)
{
//how do I test that the duck is not null,
//and has a quack method?
//if it doesn't quack, return null
}
If you have control over all of the object types that you will be using dynamically, another option would be to force them to inherit from a subclass of the DynamicObject class that is tailored to not fail when a method that does not exist is invoked:
A quick and dirty version would look like this:
public class DynamicAnimal : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
bool success = base.TryInvokeMember(binder, args, out result);
// If the method didn't exist, ensure the result is null
if (!success) result = null;
// Always return true to avoid Exceptions being raised
return true;
}
}
You could then do the following:
public class Duck : DynamicAnimal
{
public string Quack()
{
return "QUACK!";
}
}
public class Cow : DynamicAnimal
{
public string Moo()
{
return "Mooooo!";
}
}
class Program
{
static void Main(string[] args)
{
var duck = new Duck();
var cow = new Cow();
Console.WriteLine("Can a duck quack?");
Console.WriteLine(DoQuack(duck));
Console.WriteLine("Can a cow quack?");
Console.WriteLine(DoQuack(cow));
Console.ReadKey();
}
public static string DoQuack(dynamic animal)
{
string result = animal.Quack();
return result ?? "... silence ...";
}
}
And your output would be:
Can a duck quack?
QUACK!
Can a cow quack?
... silence ...
Edit: I should note that this is the tip of the iceberg if you are able to use this approach and build on DynamicObject. You could write methods like bool HasMember(string memberName) if you so desired.
Try this:
using System.Linq;
using System.Reflection;
//...
public dynamic Quack(dynamic duck, int i)
{
Object obj = duck as Object;
if (duck != null)
{
//check if object has method Quack()
MethodInfo method = obj.GetType().GetMethods().
FirstOrDefault(x => x.Name == "Quack");
//if yes
if (method != null)
{
//invoke and return value
return method.Invoke((object)duck, null);
}
}
return null;
}
Or this (uses only dynamic):
public static dynamic Quack(dynamic duck)
{
try
{
//invoke and return value
return duck.Quack();
}
//thrown if method call failed
catch (RuntimeBinderException)
{
return null;
}
}
Implementation of the HasProperty method for every IDynamicMetaObjectProvider WITHOUT throwing RuntimeBinderException.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace DynamicCheckPropertyExistence
{
class Program
{
static void Main(string[] args)
{
dynamic testDynamicObject = new ExpandoObject();
testDynamicObject.Name = "Testovaci vlastnost";
Console.WriteLine(HasProperty(testDynamicObject, "Name"));
Console.WriteLine(HasProperty(testDynamicObject, "Id"));
Console.ReadLine();
}
private static bool HasProperty(IDynamicMetaObjectProvider dynamicProvider, string name)
{
var defaultBinder = Binder.GetMember(CSharpBinderFlags.None, name, typeof(Program),
new[]
{
CSharpArgumentInfo.Create(
CSharpArgumentInfoFlags.None, null)
}) as GetMemberBinder;
var callSite = CallSite<Func<CallSite, object, object>>.Create(new NoThrowGetBinderMember(name, false, defaultBinder));
var result = callSite.Target(callSite, dynamicProvider);
if (Object.ReferenceEquals(result, NoThrowExpressionVisitor.DUMMY_RESULT))
{
return false;
}
return true;
}
}
class NoThrowGetBinderMember : GetMemberBinder
{
private GetMemberBinder m_innerBinder;
public NoThrowGetBinderMember(string name, bool ignoreCase, GetMemberBinder innerBinder) : base(name, ignoreCase)
{
m_innerBinder = innerBinder;
}
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
var retMetaObject = m_innerBinder.Bind(target, new DynamicMetaObject[] {});
var noThrowVisitor = new NoThrowExpressionVisitor();
var resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
var finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
return finalMetaObject;
}
}
class NoThrowExpressionVisitor : ExpressionVisitor
{
public static readonly object DUMMY_RESULT = new DummyBindingResult();
public NoThrowExpressionVisitor()
{
}
protected override Expression VisitConditional(ConditionalExpression node)
{
if (node.IfFalse.NodeType != ExpressionType.Throw)
{
return base.VisitConditional(node);
}
Expression<Func<Object>> dummyFalseResult = () => DUMMY_RESULT;
var invokeDummyFalseResult = Expression.Invoke(dummyFalseResult, null);
return Expression.Condition(node.Test, node.IfTrue, invokeDummyFalseResult);
}
private class DummyBindingResult {}
}
}
impromptu-interface seems to be a nice Interface mapper for dynamic objects... It's a bit more work than I was hoping for, but seems to be the cleanest implementation of the examples presented... Keeping Simon's answer as correct, since it is still the closest to what I wanted, but the Impromptu interface methods are really nice.
The shortest path would be to invoke it, and handle the exception if the method does not exist. I come from Python where such method is common in duck-typing, but I don't know if it is widely used in C#4...
I haven't tested myself since I don't have VC 2010 on my machine
dynamic Quack(dynamic duck)
{
try
{
return duck.Quack();
}
catch (RuntimeBinderException)
{ return null; }
}
Have not see a correct answer here, MS provides an example now with casting to a dictionary
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
foreach (var property in (IDictionary<String, Object>)employee)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33