Search code examples
c#asp.netwebformsmvp

How to get a reference to a web form's ModelStateDictionary from inside a Web Forms MVP Presenter?


Using the Web Forms MVP framework in an ASP.NET 4.5 Web Forms application, how do I get a reference to a page's ModelStateDictionary object from inside the Presenter object for that page?

I'd like my presenter to be able to set model state errors when something goes wrong. For example: errors when attempting to insert records that violate a UNIQUE constraint.

try
{
    dbcontext.SaveChanges();
}
catch (DbUpdateException updateException)
{
    // how to get a reference to the model state?
    ModelStateDictionary state = null;

    // add the error to the model state for display by the view
    state.AddModelError("key", updateException.GetBaseException().Message);
}

A google search for "webformsmvp presenter modelstatedictionary" yields an alarmingly low number of relevant results.


Solution

  • One way is to pass the model state from the view to the presenter as an event argument.

    First, the EventArgs class:

    public class ModelStateEventArgs : EventArgs
    {
        public ModelStateEventArgs(ModelStateDictionary modelState)
        {
            this.ModelState = modelState;
        }
    
        public ModelStateDictionary ModelState { get; private set; }
    }
    

    derive from this class if you need additional event arguments


    Then, the IView that is implemented by the view:

    public interface IDataContextView : IView<DataContextVM>
    {
        event EventHandler<ModelStateEventArgs> Update;
    }
    

    Raising the event in the view itself:

    • MvpPage views

      this.Update(this, new ModelStateEventArgs(this.ModelState));
      
    • MvpUserControl views

      this.Update(this, new ModelStateEventArgs(this.Page.ModelState));
      

    Finally, the Presenter, which can subscribe to the Update events and get the model state for each event as it happens:

    public class DataContextPresenter : Presenter<IDataContextView>
    {
        public DataContextPresenter(IDataContextView view)
            : base(view)
        {
            this.View.Update += OnUpdating();
        }
    
        private void OnUpdating(object sender, ModelStateEventArgs e)
        {
            var entity = ConvertViewModelToEntity(this.View.Model);
            dbcontext.Entry(entity).State = EntityState.Modified;
            try
            {
                dbcontext.SaveChanges();
            }
            catch (DbUpdateException updateException)
            {
                // add the error to the model state for display by the view
                e.ModelState.AddModelError(string.Empty, updateException.GetBaseException().Message);
            }
        }
    }