ASP.NET - Separation of Concerns

Imagine the following scenario: we have a page containing controls A and Control B.

Say Control A has a button, and when that button is pressed, we want Control B to respond. But we want to do it in an abstract way, that is, we cannot have Control B knowing anything about Control A, and vice versa.

This way we can develop these controls in isolation and manage them through unit testing.

Now I thought I had a solution, just want to know what you guys think about it.

Incl. Control. Click the "Me" button, I put a "message" on the session, i.e. session ["MESSAGES"] = "ControlA_Click".

In Page1, on page_LoadComplete () I put a call to ProcessMessages, which looks like this:

            List<Message> messages = SessionMessages.GetMessageList(Page);
        foreach(Message m in messages)
        {
            //Get Controls
            ControlA controlA = FindControl("controlA") as ControlA;
            controlA .ProcessMessage(m);

            ControlB controlB = FindControl("controlB") as ControlB;
            controlB.ProcessMessage(m);
      }

      

in ControlB's ProcessMessage () method, we can respond to messages that ControlB is interested in, for example:

    if (m.MessageName == SessionMessages.C_MESSAGE_SEARCH)
{
    this.Visible = true;
}

      

I think it works. This allows us to design these controls completely separate from each other, while still allowing cross-control communication at an abstract level.

The only thing I can think of about what might be causing the crash is perhaps the ASP.NET lifecycle with respect to pages and user controls. The way I understand this is that ALL events had to be handled on the controls before the Page_LoadComplete () function was called on the ownership page.

Thoughts?

+1


source to share


7 replies


What you have is an EventBroker . I don't think Session is the right place to do this, since you don't have to live on demand. The HttpContext might work, but if I don't want the message bus to be split between IHttpModules and IHttpHandlers, I would probably just use a Page Class base where custom controls can dispatch their page instance:

interface IEventBroker {
 void Send(Message m);
}

class ControlA {
  void MyButton_Click(object sender, EventArgs e) {
     var eb = this.Page as IEventBroker;
     if (eb != null) eb.Send(new Message());
  }
}

      



or give the controls a reference to the EventBroker - in which case I'll probably make the EventBroker myself a control and pass an ID to each control so they can use the Page.FindControl parameter.

+1


source


  • Control A should raise an event
  • The page that contains the controls subscribes to the event and then calls the appropriate method on the other control.
  • Control B should handle message ()


+6


source


interesting session abuse ...

you could also have a message queue on the hosting page instead of

I would recommend that you instead have your hosting page do something to the control in response to the message, instead of making the control "smart" - there is really no need for the button to be "smart"

+2


source


As Briggy says, this is exactly what the Model-View Presenter is talking about. Here's an article around MVP in .NET if you'd like to review your own.

Ideally, you want to look at the MVC framework as an example of what you can do when you highlight everything.

What I usually do is this button click event raises a domain specific event like:


private void ControlA_OnClick(..)
{
  if(LoginRequested != null)
    LoginRequested(this, loginObj);
}

      

Thus, it becomes clear why someone pressed the button and brought home the division.

+2


source


Isn't that data binding? Control A responds to an event that updates the model and then invokes data binding to its dependencies.

If you want to create a messaging system, the design for the publisher and subscriber does not need to know about each other, but only the message itself. Create an interface something like this:

public interface IHandle<T> where T:IMessage
{
     void Process(T message)
}

      

You will need a method of discovering which controls implement it and building a messagetype-> handler map, see how the core DI frameworks handle nesting properties in ASP.NET controls to see how you can do this. Then you can use a single SendMessage method, which is responsible for sending a message to all controls that can process that message. This is more common in this kind of pattern in UI forms.

+1


source


Review the Managed Extensibility Framework Contrib Project. They only have a sample website that is exactly what you want.

0


source


There are some problems with this approach, such as:
- "Events" are not checked at compile time (you can easily mistake the name of an event and find out about it at runtime or in the worst case)
- Populate the session with communication

- You must enter the control names as a string - If there is more than one control subscribing to this event, it can become difficult to control - When parameters have to be sent between controls, the solution becomes more difficult to manage.

The best approach is to use the build mechanism in an event by declaring events on the controls:

public event EventHandler SpecialClick;

      

Every control that needs to do something will subscribe to this event

controlA.SpecialClick += new EventHandler(controlA_SpecialClick)

      

using regular dot.net events.

0


source







All Articles