I'm working in an old project (web forms). I'm adding a new module to the system. Specifically, enable and disable roles massively.
In the web form RoleAssignment, I have methods that differ depending on the operation to be performed (enable or disable). So, I'm using switch-case and if-else blocks to know what type of operation is selected.
I would like to decouple that functionality to not use switch-case blocks.
Well, what I've tried is create a class Operation that has methods like LoadUsers(), ExecuteAction(), etc. Then, two classes Enabling and Disabling that inherit from Operation like this:
public abstract class Operation : RoleAssignment
{
public abstract void LoadUsers();
public abstract void ExecuteAction();
}
public class Enabling: Operation
{
protected void LoadUsers()
{
//Calling sp that load users who don't have the selected role
}
protected void ExecuteAction()
{
...
}
}
public class Disabling: Operation
{
protected void LoadUsers()
{
//Calling sp that load users who have the selected role
}
protected void ExecuteAction()
{
...
}
}
Currently my web form is (summarized):
public partial class RoleAssignment: Page
{
protected void Page_Load(object sender, EventArgs e)
{
LoadUsers();
}
private void LoadUsers()
{
//This is what I intend to eliminate
switch(ddlOperation.SelectedValue)
{
case "enable": break;
case "disable": break;
}
}
...
}
I tried change the web form to this, but it didn't work:
public partial class RoleAssignment: Page
{
private Operation operation;
protected void Page_Load(object sender, EventArgs e)
{
//This would be the only switch-case block that I would use
switch(ddlOperation.SelectedValue)
{
case "enable": operation = new Enabling(); break;
case "disable": operation = new Disabling(); break;
}
LoadUsers();
}
private void LoadUsers()
{
operation.LoadUsers(); //No need to use switch-case block
}
private void ExecuteAction()
{
operation.ExecuteAction(); //No need to use switch-case block
}
...
}
The problem is when it creates an instance of Operation, it creates a new Context of RoleAsignment I mean, all variables are null.
I don't know if you understand what I want to do and if exist a simple way to solve this.
Related
There are two classes that interact in this problem. I'd like to note I'm using Unity:
TaskHandler
public class TaskHandler{
public event Action<GameObject> TaskResponses;
private void Update(){
if (someCondition){
TaskResponses?.Invoke(taskObj);
}
}
}
TaskBase
public class TaskBase: MonoBehaviour{
private TaskHandler taskHandler;
private void Start(){
taskHandler = gameObject.GetComponent<TaskHandler>();
taskHandler.TaskResponses += TaskResponse;
}
private void TaskResponse(GameObject taskObj){
//if check so that only specific TaskResponses run.
if (taskObj == gameObject){
//functions
}
}
}
The problem I'm facing is with methods that extend TaskResponse().
public class SpecificTask{
public override void TaskResponse(GameObject taskObj)
{
base.TaskResponse(taskObj);
//another if check
if (taskObj == thisTaskObj){
//some other functionality
}
}
}
I don't want to do another if check. I tried the following:
public class TaskBase: MonoBehaviour{
//Start() method omitted
private void TaskResponse(GameObject taskObj){
//if check so that only specific TaskResponses run.
if (taskObj == gameObject){
//functions
}
else{
//Effectively stops code from SpecificTask to continue running,
//But other Actions are no longer called.
return;
}
}
}
But the return statement stops TaskReponses() from other classes to run. By that, I mean that if I had Class Task1 and Task2, and Task1's TaskResponse() runs first, but it runs the else statement, it stops and does not run Task2's TaskResponse().
How can I improve my code to stop writing repetitive if checks, while have my code check all Action like I want it to? Should I not be using event for this scenario at all?
Thank you!
You could make it not void but rather bool which indicates if the method was successfully terminated or aborted like e.g.
public class TaskBase
{
public virtual bool TaskResponse(GameObject taskObj)
{
if(taskObj != thisObj) return false;
// Default stuff to happen
return true;
}
}
Then you can do
public class MyTask
{
public override bool TaskResponse (GameObject taskObj)
{
if(!base.TaskResponse(taskObj)) return false;
// Default stuff already happened
// Now you can add additional stuff here
return true;
}
}
Alternatively if you want to avoid that if check entirely what I also do often is using separate methods like
public class TaskBase
{
public void TaskResponse (GameObject taskObj)
{
if(taskObj != thisObj) return;
TaskResponseInternal();
}
protected virtual void TaskResponseInternal()
{
// Default stuff to happen
}
}
And then simply override that instead
public class MyTask
{
protected override void TaskResponseInternal ()
{
// If you want also the default stuff
base.TaskResponseInternal();
// Additional stuff to happen
}
}
ASP.NET C#
I have a question, how can I make an access control to a request provided by a botton, to stop the execution of the function, I need something generic in which it can be configured and say that roles or profiles can access to certain functions request Executed by a button.
I don't want something like that
protected void DownloadFile_ServerClick(object sender, EventArgs e)
{
if (RoleAdmin)
{
// do something
}
}
I need something that directly validates in the request of the pag when the method is executed, to see if that profile matches with the method stored in the base, so I do for all pag and do not have to put it in hard in each one of the executed methods.
I need the name of fucntion that is request.
public class PageBase : Page
{
protected override void OnLoad(EventArgs e)
{
***How to capture the function name of request ???***
if (User.Identity.IsAuthenticated == false) { Response.Redirect("~/Account/login.aspx?ReturnUrl=/admin"); };
if (!(User.IsInRole("admin") || User.IsInRole("super user"))) { Response.Redirect("/"); };
}
}
Maybe with this:
public class StaticObjects
{
public static string UserRole
{
get
{
try
{
return (string)HttpContext.Current.Session["UserRole"];
}
catch (Exception)
{
return "";
}
}
set
{
HttpContext.Current.Session["UserRole"]=value;
}
}
public static bool AuthorizeExecution(EventHandler method)
{
bool autorized = YourDataBaseQuery(UserRole, method.Method.Name);
return autorized;
}
}
////////////////////////////// ANOTHER FILE /////////////////
public static void DownloadFile_ServerClick(object sender, EventArgs e)
{
//You send the method itself because it fits the delegate "EventHandler"
if(!StaticObjects.AuthorizeExecution(DownloadFile_ServerClick))
return;
}
I have an application where I would like to execute certain orders on a certain thread when that thread is idling. So I created a manager to handle this for me, launched of a form.show and created a thread manager:
public class ThreadManager
{
static List<ThreadAble> orders = new List<ThreadAble>();
public static bool running = false;
public static void execute(ThreadAble action)
{
orders.Add(action);
}
public static void RegisterAPIThreadAndHold()
{
running = true;
Application.Idle += Application_Idle;
}
private static void Application_Idle(object sender, EventArgs e)
{
if (orders.Count != 0)
{
ThreadAble f = orders.First();
orders.Remove(f);
f.execute();
}
}
}
public interface ThreadAble {
void execute();
}
public static class formstuff{
private static void ShowDialogThreaded(){
form.Show(owner);
ThreadManager.RegisterAPIThreadAndHold();
}
}
}
I then try to use this using it by:
public class TestRegister : ThreadAble
{
public void execute()
{
throw new NotImplementedException();
}
}
ThreadManager.execute(new TestRegister());
Now this should throw an exception, however it doesn't. I have also tried with more complicated behaviour and breakpoints but this code seems to never get executed. Am I misunderstanding how the Application_Idle works? Is there another way to make it so that this thread starts executing my code (has to be this thread) when it's done with handling the GUI code and not doing anything else (it might be required to do other things a well).
I already veritfied that RegisterAPIThreadAndHold() is executed.
I have mad a custom control. and i need to redirect the Event handler. i have cut the code down dramatically to try and articulate what im trying to do.
public class RemoteDesktop : WindowsFormsHost
{
public event OnConnectingEventHandler OnConnecting;
public delegate void OnConnectingEventHandler(object sender, EventArgs Arguments);
public event OnDisconnectingEventHandler OnDisconnecting;
public delegate void OnDisconnectingEventHandler(Object sender, IMsTscAxEvents_OnDisconnectedEvent Arguments);
private AxMsRdpClient7NotSafeForScripting RDPUserControl = new AxMsRdpClient7NotSafeForScripting();
public RemoteDesktop()
{
this.RDPUserControl.BeginInit();
this.RDPUserControl.SuspendLayout();
base.Child = RDPUserControl;
this.RDPUserControl.ResumeLayout();
this.RDPUserControl.EndInit();
}
}
public class RemoteDesktopViewModel
{
public RemoteDesktopViewModel()
{
RemoteDesktop newRDC = new RemoteDesktop();
newRDC.OnConnecting += new RemoteDesktop.OnConnectingEventHandler(newRDC_OnConnecting);
}
void newRDC_OnConnecting(object sender, EventArgs Arguments)
{
//DoStuff
}
}
basically it all works, i can connect and disconnect to the remote computer however i cannot get the fired events to occur in my view model.
Can anyone help me figure out how i can point my events correctly.
Thank you.
Thanks to some help i have the resolution
Step 1:
Declare delegates outside the class (within the namespace)
Step 2:
Declare the events to be called for the control.
Step 3: use the event handlers of the controls to reise the delegates you created
Completed Code
public delegate void OnConnectingEventHandler(object sender, EventArgs Arguments);
public delegate void OnDisconnectingEventHandler(Object sender,IMsTscAxEvents_OnDisconnectedEvent Arguments);
public class RemoteDesktop : WindowsFormsHost
{
public event OnConnectingEventHandler IsConnecting;
public event OnDisconnectingEventHandler IsDisconnecting;
private AxMsRdpClient7NotSafeForScripting RDPUserControl = new AxMsRdpClient7NotSafeForScripting();
public RemoteDesktop()
{
this.RDPUserControl.BeginInit();
this.RDPUserControl.SuspendLayout();
base.Child = RDPUserControl;
this.RDPUserControl.ResumeLayout();
this.RDPUserControl.EndInit();
RDPUserControl.OnConnecting += RemoteDesktop_OnConnecting;
RDPUserControl.OnDisconnected += RDPUserControl_OnDisconnected;
}
void RDPUserControl_OnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
{
IsDisconnecting(sender, e);
}
void RemoteDesktop_OnConnecting(object sender, EventArgs Arguments)
{
IsConnecting(sender, Arguments);
}
}
public class RemoteDesktopViewModel
{
public RemoteDesktopViewModel()
{
RemoteDesktop newRDC = new RemoteDesktop();
newRDC.IsConnecting += new RemoteDesktop.OnConnectingEventHandler(newRDC_OnConnecting);
}
void newRDC_OnConnecting(object sender, EventArgs Arguments)
{
//DoStuff
}
}
//at the constractor of the class
OnConnecting+=RDC_OnConnecting;
then you can write your logic in method:newRDC_OnConnecting. make sure OnConnectingEventHandler have same method signatures with newRDC_OnConnecting.
I'm attempting to use the new ASP.NET Identity 2.0 authentication system(s) in a WebForms application, but I'm having trouble validating a user before allowing the data source for users to save.
The trouble stems from calling IIdentityValidator.ValidateAsync from the data source's OnUpdating event. The markup is functionally identical to the default Dynamic Data templates (except for the addition of Async="true"), with a few customizations in the code behind. Basically, I manually set the MetaTable for the request (since this page is a replacement for one of my dynamic data routes, but I'd like to keep the benefit of scaffolded properties) and I've added the DetailsDataSource_Updating event. Though the code sample below successfully saves the user to our database, the following error is usually thrown before returning to the client:
"An asynchronous module or handler completed while an asynchronous operation was still pending."
I've spent a considerable amount of time attempting to get this to work, but have yet to find a solution that does not lock up the page or throw the above error. I fear that I am completely misunderstanding async/await in WebForms, or worse, that async/await is only really usable for database queries/binding outside of MVC.
public partial class Edit : System.Web.UI.Page
{
protected UserManager manager;
protected CustomMetaTable table;
protected void Page_Init(object sender, EventArgs e)
{
manager = UserManager.GetManager(Context.GetOwinContext());
table = Global.DefaultModel.GetTable(typeof(User)) as CustomMetaTable;
DynamicDataRouteHandler.SetRequestMetaTable(Context, table);
FormView1.SetMetaTable(table);
DetailsDataSource.EntityTypeFilter = table.EntityType.Name;
}
protected void Page_Load(object sender, EventArgs e)
{
Title = table.EntityName;
DetailsDataSource.Include = table.ForeignKeyColumnsNames;
}
protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName == DataControlCommands.CancelCommandName)
{
Response.Redirect(table.ListActionPath);
}
}
protected void FormView1_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
{
if (e.Exception == null || e.ExceptionHandled)
{
Response.Redirect(table.ListActionPath);
}
}
protected async void DetailsDataSource_Updating(object sender, Microsoft.AspNet.EntityDataSource.EntityDataSourceChangingEventArgs e)
{
IdentityResult result = await manager.UserValidator.ValidateAsync(e.Entity as User);
if (!result.Succeeded)
{
e.Cancel = true;
}
}
In the process of writing a new UserValidator with a synchronous Validate method, I found a class in the Identity assembly which is used in all the synchronous wrappers for UserManager and RoleManager. I copied this class into my project and it has allowed me to consume async methods synchronously with only a few exceptions (the primary exception seems to be avoided by assigning the result to a variable before referencing it elsewhere).
internal static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new TaskFactory(
CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
}
public static void RunSync(Func<Task> func)
{
_myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
}
}
Usage:
AsyncHelper.RunSync(() => manager.UserValidator.ValidateAsync(e.Entity as User));