Acumatica Override _(FieldVerifying<field> e) - overriding

I need to override this event in ARInvoiceEntry.
protected virtual void _(Events.FieldVerifying<ARTran.curyRetainageAmt> e)
This is the code I have to override the above.
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
#region Event Handlers
public delegate void _Delegate(Events.FieldVerifying<ARTran.curyRetainageAmt> e);
[PXOverride]
public void _(Events.FieldVerifying<ARTran.curyRetainageAmt> e, _Delegate baseMethod)
{
baseMethod(e);
}
#endregion
}
However the above is giving me an error:
Invalid argument type in the event handler PX.Objects.AR.ARInvoiceEntry_Extension::_
How would I override an "_" event method?
I have tried this, which then doesn't override the method.
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
#region Event Handlers
[PXOverride]
public void _(Events.FieldVerifying<ARTran.curyRetainageAmt> e)
{
// do my stuff
}
#endregion
}

With event handlers, you do not have to do pxoverride. You add a second method with the same signature, and then can call the basemethod parameter.
public void _(Events.FieldVerifying<ARTran.curyRetainageAmt> e, PXFieldVerifying baseMethod)
{
baseMethod?.Invoke(e.Cache, e.Args);
}
the ?.Invoke calls the base function only if it is set, so you do not need to check for nulls.

Related

Wait for Base Onload event

Trying to make use of Async await in ASP.Net Webforms.
Consider I have a base user control as below
public class BaseUserControl :UserControl
{
public int SomeBaseValue { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Page.RegisterAsyncTask(new PageAsyncTask(PageLoadAsync));
}
public async Task PageLoadAsync()
{
SomeBaseValue = await GetBaseValueFromDB();
}
}
An EmployeeUserControl that derives from BaseUserControl
public class EmployeeUserControl : BaseUserControl
{
public int SomeDerivedValue { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e); //Want this method to wait for the completion of base class's async method
SomeDerivedValue = base.SomeBaseValue * 2;
}
}
So the derived class has a property named SomeDerivedValue that depends on the base class's
SomeBaseValue, so I want, when the Derived Class base.OnLoad is called it should wait for the BaseUserControl's OnLoad method completion including the completion of Async Method.
As of now the execution doesnt wait for the completion of Async method, so the SomeBasevalue is null when it executes the line SomeDerivedValue = base.SomeBaseValue * 2;
Is there anyway to achieve this?
You might think adding a TaskCompletionSource to BaseUserControl would solve it, but it would (probably - haven't tried) deadlock the page.
Web Forms only supports async/await in PageAsyncTasks. Those respect the recommended lifetime for page processing.
Using Asynchronous Methods in ASP.NET 4.5

Custom MapBox Android Renderer - crash when change tabs

I am trying to create a MapBox Renderer for Android in Xamarin Forms using the naxam library.
The map is displaying well as a content of a view in a tab, however when I change tab several times it crashes on the android emulator. I suppose the problem comes from the renderer but can't figure out where.
Here is a part of my code :
public class MapViewRenderer : ViewRenderer<ContentView, Android.Views.View>,
IOnMapReadyCallback, Com.Mapbox.Mapboxsdk.Maps.Style.IOnStyleLoaded
{
private MapView _mapView = null;
private MapboxMap _mapBox = null;
public MapViewRenderer(Context context) : base(context)
{
Mapbox.GetInstance(Context, "pk.###");
}
public void OnMapReady(MapboxMap p0)
{
_mapBox = p0;
[...]
}
public void OnStyleLoaded(Com.Mapbox.Mapboxsdk.Maps.Style p0)
{
[...]
}
protected override void OnElementChanged(ElementChangedEventArgs<ContentView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_mapView = new MapView(Context);
_mapView.GetMapAsync(this);
view.Content = _mapView.ToView();
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_mapView.Dispose();
}
base.Dispose(disposing);
}
}
All the examples I read on the net are about creating the MapView in the main activity with OnCreate, OnStart, OnResume... I haven't found any about creating a map in a custom render.
Please help.
EDIT :
---------------------------------SOLUTION---------------------------------
The problem was fixed using the code below in the custom renderer. In addition the renderer uses a Mapview instance which has been moved inside the main activity following ToolmakerSteve's remark.
MapViewRenderer.cs :
public class MapViewRenderer : ViewRenderer<ContentView, Android.Views.View>
{
public MapViewRenderer(Context context) : base(context)
{}
protected override void OnElementChanged(ElementChangedEventArgs<ContentView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var view = e.NewElement as Views.Map;
if (Control == null)
{
SetNativeControl(MainActivity.MainActivityInstance.MapView);
}
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
MainActivity.MainActivityInstance.MapView.RemoveFromParent();
}
base.Dispose(disposing);
}
}
MainActivity.cs :
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IOnMapReadyCallback, Style.IOnStyleLoaded
{
public MapView MapView { get; private set; } = null;
public MapboxMap MapboxMap { get; private set; } = null;
public static MainActivity MainActivityInstance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
[...]
MainActivityInstance = this;
Mapbox.GetInstance(this, "pk.###");
MapView = new MapView(this);
MapView.GetMapAsync(this);
MapView.OnCreate(savedInstanceState);
}
protected override void OnStart()
{
base.OnStart();
MapView.OnStart();
[...]
}
protected override void OnResume()
{
base.OnResume();
MapView.OnResume();
}
protected override void OnPause()
{
MapView.OnPause();
base.OnPause();
}
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
MapView.OnSaveInstanceState(outState);
}
protected override void OnStop()
{
base.OnStop();
MapView.OnStop();
}
protected override void OnDestroy()
{
MapView.OnDestroy();
base.OnDestroy();
}
public override void OnLowMemory()
{
base.OnLowMemory();
MapView.OnLowMemory();
}
public void OnMapReady(MapboxMap p0)
{
MapboxMap = p0;
[...]
}
public void OnStyleLoaded(Com.Mapbox.Mapboxsdk.Maps.Style p0)
{
[...]
}
}
Wrap the contents of each method in try-catch, and write to Debug output any exception (hopefully instead of crashing).
You will probably need to find out exactly what causes the crash, for anyone to help you.
Do this by adding Debug.WriteLine statements throughout the custom renderer.
I also recommend verifying that it really is the custom renderer that causes the problem.
Do this by commenting out most of the custom code. So that it displays as an empty view.
You need to add code to the MainActivity methods. This won't fix this crash, but it will avoid crashing later, for example when app goes into background.
Naxam library install guide says:
The MapView contains its own lifecycle methods for managing Android's OpenGL lifecycle, which must be called directly from the containing Activity. In order for your app to correctly call the MapView's lifecycle methods, you must override the following lifecycle methods in the Activity that contains the MapView and call the respective MapView method.
Android code from that link:
// Set this from your custom renderer.
public MapView mapView;
override fun onStart() {
super.onStart()
mapView?.onStart()
}
override fun onStop() {
super.onStop()
mapView?.onStop()
}
override fun onLowMemory() {
super.onLowMemory()
mapView?.onLowMemory()
}
override fun onDestroy() {
super.onDestroy()
mapView?.onDestroy()
}
Translate that into C# equivalent.
In your custom renderer, set the activities mapView variable:
Xamarin Essentials.Platform.CurrentActivity.mapView = ...;
You should also set that variable to null:
in OnElementChanged / e.newElement == null
in Dispose.
In my experience, on Android, OpenGL views don't like to be hidden - which is what happens when switching to different tab. (MapBox uses an OpenGL view.)
Unfortunately the result is a "hard crash" - won't be caught by try/catch. Won't give useful information about why it crashed.
If this is the cause, none of the above will fix the problem.
You might have to do custom logic that disposes the map when the tab is hidden, recreates it when the tab comes back.
See https://stackoverflow.com/a/52186885/199364, for the event you need to add code to.

Call method on hub from HubPipelineModule OnIncomingError event

I need to implement custom error logging on signalR hubs. This can be done by creating ErrorModule which will inherit from HubPipelineModule and it will be registered on Startup like this
GlobalHost.HubPipeline.AddModule(new ErrorModule());
This is my hub
public class FooHub : Hub
{
public void MethodWithException()
{
throw new Exception();
}
public void FooMethod()
{
}
}
And this is my module
public class ErrorModule : HubPipelineModule
{
protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext)
{
//call foo method on foo hub
//log error
}
}
Lets say MethodWithException() is called. It is possible to call FooMethod() on hub which invoked event OnIncomingError ?
With something like this :
protected override void OnIncomingError(ExceptionContext exceptionContext,
IHubIncomingInvokerContext invokerContext)
{
dynamic caller = invokerContext.Hub.Clients.Caller;
caller.ExceptionHandler(exceptionContext.Error.Message);
//log something here
Debug.WriteLine(exceptionContext.Error.Message);
}
EDIT
To call a particular method of the hub you can do :
protected override void OnIncomingError(ExceptionContext exceptionContext,
IHubIncomingInvokerContext invokerContext)
{
var hub = (invokerContext.Hub as HubType); //
hub.MyMethod("myparam","mysecondparam");
//log something here
Debug.WriteLine(exceptionContext.Error.Message);
}
You can find the full code here : How to handle SignalR server exception at client?

ASP.NET is System.Web.UI.Page thread safe

I am wondering if the following code is thread safe?
Can i be be sure that UniqueFoo will indeed be the Unique Foo and will not be override?
public partial class Dummy : System.Web.UI.Page
{
public string UniqueFoo{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var id = int.Parse(Request["Id"]);
UniqueFoo = SomeThreadSafeWCF.GetUniqueFoo(id);
}
}
what about the following (static)
public partial class Dummy : System.Web.UI.Page
{
public static string UniqueFoo{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var id = int.Parse(Request["Id"]);
UniqueFoo = SomeThreadSafeWCF.GetUniqueFoo(id);
}
}
i later want to use UniqueFoo in a [WebMethod]
[WebMethod]
public static void SetSomeObject(SetSomeObject obj)
{
SomeThreadSafeWCF service = new SomeThreadSafeWCF ();
service.SetSomeObject(UniqueFoo, obj);
}
EDIT:
I am getting SetSomeObject from JS and UniqueFoo is coming from ASP.NET
will i have any issues when NOT using the static in my Dummy class according to your answers?
Surely your first sample is thread safe because when a request of a page post to the Web Server asp.net make new instance of your page and call page_load so if your SomeThreadSafeWCF.GetUniqueFoo() always make a unique Foo everything is thread save
Your second code snippet is not thread safe because you are modifying the value of a static field. So for example if later in this page you attempt to read the value of this UniqueFoo field you might not get the value you expect.
The first code snippet is fine because the field is not static.
If you want to use the UniqueFoo in a WebMethod then I would recommend you to pass it to this web method when calling it.
[WebMethod]
public static void SetSomeObject(SetSomeObject obj, string uniqueFoo)
{
SomeThreadSafeWCF service = new SomeThreadSafeWCF ();
service.SetSomeObject(uniqueFoo, obj);
}

IoC and dataContext disposing in asp.net mvc 2 application

I have the Global.asax like the code below:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
// ....
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(typeof(IOCControllerFactory));
}
}
public class IOCControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public IOCControllerFactory()
{
kernel = new StandardKernel(new NanocrmContainer());
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return base.GetControllerInstance(requestContext, controllerType);
var controller = kernel.TryGet(controllerType) as IController;
if (controller == null)
return base.GetControllerInstance(requestContext, controllerType);
var standartController = controller as Controller;
if (standartController is IIoCController)
((IIoCController)standartController).SetIoc(kernel);
return standartController;
}
class NanocrmContainer : Ninject.Modules.NinjectModule
{
public override void Load()
{
// ...
Bind<DomainModel.Entities.db>().ToSelf().InRequestScope().WithConstructorArgument("connection", "Data Source=lims;Initial Catalog=nanocrm;Persist Security Info=True;User ID=***;Password=***");
}
}
}
In this case if somewhere it is the class, defined like:
public class UserRepository : IUserRepository
{
private db dataContext;
private IUserGroupRepository userGroupRepository;
public UserRepository(db dataContext, IUserGroupRepository userGroupRepository)
{
this.dataContext = dataContext;
this.userGroupRepository = userGroupRepository;
}
}
then the dataContext instance is created (if no one was created in this request scope) by Ninject.
So the trouble now is - where to invoke dataContext method .Dispose()?
UPD:
so i followed the advice from KeeperOfTheSoul and solved the issue in such way:
public override void ReleaseController(IController controller)
{
base.ReleaseController(controller);
var db = kernel.Get<DomainModel.Entities.db>();
db.Dispose();
}
A good place to handle this is in IControllerFactory.ReleaseController, eg
public override void ReleaseController() {
base.ReleaseController();
//Do whatever you need to clean up the IoC container here
}
In NInject this could be handled by scoping using an activation block, at the start of the request when creating the controller you can store the activation block in the HttpContext's current items, during ReleaseController you can retrieve the previously created activation block and dispose it.
You could also consider using InScope and having the custom scope implement INotifyWhenDisposed. After that the usage is the same as with an activation block, except now you store the scope in the HttpContext's current items.
A pattern that is sometimes used to dispose db connections is to call Dispose from the finaliser.
public class db : IDisposable {
//called by the garbage collector
~db() {
//Call dispose to make sure the resources are cleaned up
Dispose(false);
}
//IDisposable implementation
public void Dispose() {
Dispose(true);
}
//subclasses of db can override Dispose(bool) and clean up their own fields
protected virtual void Dispose (bool disposing) {
if (disposing) {
//Supress finalization as all resources are released by this method
//Calling Dispose on IDisposable members should be done here
GC.SupressFinalize();
}
//Clean up unmanaged resources
//Do not call other objects as they might be already collected if called from the finalizer
}
}
You could hook it into Application_EndRequest.

Resources