Search code examples
c#asp.netscreen-scrapingmvp

Better way to handle screen scrape object


In my applications I always end up implementing a Model-View-Presenter pattern and usually end up scrapping my View object from the screen with a get property.

For example

Person IBasicRegistration.Person
{
 get
 {
  if (ViewState["View.Person"] == null)
   ViewState["View.Person"] = new Person();

  var Person = (Person) ViewState["View.Person"];

  Person.Email = txtEmail.Text.Trim();
  Person.FirstName = txtFirstName.Text.Trim();
  Person.LastName = txtLastName.Text.Trim();
  Person.Zip = txtZip.Text.Trim();
  Person.Phone = txtPhone.Text.Trim();
  Person.ResidentPersonLicenseState = 
        EnumerationParser.Parse<States?>(ddState.SelectedValue);

  return Person;
 }
}

However during debugging I've noticed when I access IBasicRegistration.Person in my Presenter/Model that I get quite a few traversals of my get { } property.

I started thinking this pattern seems to very similar to the INotifyPropertyChanged pattern and I started thinking about implementing a similar pattern and having each textfield implement an OnChanged event that would update it's related value in the person object that sits in the view state however the further I thought on that it require numerous server requests every time a person mouses out of a field and seems like it could lead to scalability issues at some point.

My next thought would it just make sense to create an IsDirty flag and wrap my code where it touches the fields similar to:

Person IBasicRegistration.Person
{
 get
 {
  if (ViewState["View.Person"] == null)
   ViewState["View.Person"] = new Person();

  var Person = (Person) ViewState["View.Person"];

  if(IsDirty)
  {
      Person.Email = txtEmail.Text.Trim();
      ...others

      IsDirty = false;
  }

  return Person;
 }
}

And set on any method that invokes a post back, (ie usually just the submit button) to set IsDirty = true and then it will skip repeating alot of work for no reason.

Has anyone come up with something more elegant for this task?


Solution

  • I think where the disconnect is happening is that you typically implement a view while in your get you are create the view. A typical scenario is that a form implements a view interface and then register itself (or is registered) within the application object. Then anytime you need to find out what has been entered for a person you use the various properties of the view.

    For example to find out what you entered for the first name you would go

     myVariable = PersonView.FirstName();
    

    In your example you are pulling the STATE of the view every time you access person. Even if you just wanted the email you are pulling everything and putting it in a state variable.

    Now this if the data structure Person was part of your model. Then this could be OK. You pull the person out once when it is changed. Modify or add it to the model then everything else (reports ,etc) would be looking at the model.

    However your question suggests that that it is being hit over and over again. Which leads me to think that Person is being accessed directly from the view for a variety of reasons. In this case I would put properties on the view allowing access to the individual members.

    Or I would refactor the design so that everything uses the model for the data with the model being updated everytime the view changes. I suspect you probably don't want to do this at this point and hence the best way is to use individual properties.