Separation of concerns in asp.net cause hierarchy mess - asp.net

I’m designing a back office web site, one that will enable administrators to manage content, products, prices and such. I have two issues I’d like to solve in a base class that each page controller (i.e. code-behind class) will extend, and these are:
Storing of ViewState on disk, and
User validation.
Furthermore, I would like each page controller to follow the same design when it comes to setting event handlers, populating the form and saving the data. I would like to solve this issue by creating abstract methods that the page controllers implement.
Now, creating a base class that caters for ViewState storage and user validation, and furthermore defines how and when event handlers are set, forms are populated and data is persisted to me is too much of a mess. I like a high degree of separation of concerns and I’m drawn towards creating three base classes:
System.Web.UI.Page
|
FileSystemStatePage : System.Web.UI.Page
(storing of ViewState)
|
SecurePage : FileSystemStatePage
(user validation)
|
PageBase : SecurePage
(abstract, defines methods for setting event handlers, form population, saving)
Now I am quite happy with the separation of concerns, but I’m not thrilled about the deep class hierarchy. What if I find myself in the need of user validation but not ViewState on disk? So...
...how do you guys usually solve these issues?
public class FileSystemStatePage : Page
{
protected override void SavePageStateToPersistenceMedium(object viewState)
{
// Serialize ViewState...
// Save to disk...
}
protected override object LoadPageStateFromPersistenceMedium()
{
// Read file content...
// Deserialize and return...
}
}
public class SecurePage : FileSystemStatePage
{
protected override void OnInit(EventArgs e)
{
if (!ValidateUser()) Response.Redirect("~/Login.aspx");
base.OnInit(e);
}
protected virtual bool ValidateUser()
{
return LoginHelper.LoggedInSystemUser != null;
}
}
public abstract class PageBase : SecurePage
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
SetEventHandlers();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
Populate();
}
}
protected abstract void SetEventHandlers();
protected abstract void Populate();
protected abstract void OnCancel(object sender, EventArgs e);
protected abstract void OnSave(object sender, EventArgs e);
}

I'd have to say, with no particular solution, that a good separation of concerns is actually disrupted in the above nested hierarchy. It appears that the functional pieces should be further separated as to not be included every time the other is needed.
Why is it necessary that you have viewstate and validation in the same space? Why not separate it altogether?

Related

OnAppearing not called in prism xamarin forms

I want a process to be called each time I navigated to my view to refresh a list.
I am using Xamarin Forms and prism framework.
I made my ViewModel derivate from ContentPage but the following method is never called :
protected override void OnAppearing()
{
//Do things
}
How am I supposed to do to get the event? Is it better to use OnNavigateTo?
Through the document:
There are times in your application where you may want to invoke code
in your ViewModel based on when the Page Appears or Disappears without
Navigation specific consideration. For these times you can utilize the
IPageLifecycleAware interface to properly respond to the Appearing and
Disappearing events from the Page.
public class ViewAViewModel : IPageLifecycleAware
{
public void OnAppearing()
{
Console.WriteLine("We are appearing");
}
public void OnDisappearing()
{
Console.WriteLine("We are disappearing");
}
}
I found a solution to make my code work, I add to do this in my code behind from the page:
protected override void OnAppearing()
{
(BindingContext as IPageLifecycleAware)?.OnAppearing();
}
Still a mystery why I need to add this and it is not in the sample.
at the time of this post, the sample does it differently. It uses Behaviors to achieve expectation
It has a PageLifeCycleAwareBehavior class
private void OnAppearing(object sender, EventArgs e)
{
MvvmHelpers.InvokeViewAndViewModelAction<IPageLifecycleAware>(AssociatedObject, aware => aware.OnAppearing());
}
private void OnDisappearing(object sender, EventArgs e)
{
MvvmHelpers.InvokeViewAndViewModelAction<IPageLifecycleAware>(AssociatedObject, aware => aware.OnDisappearing());
}
You can see the full implementation here
You can also call Initialize is a good alternative
Add ini to your class
public class HelloViewModel : BindableBase, IInitialize
then add the following method
public void Initialize(INavigationParameters parameters)
{
// Do stuff
}

Mini-Profiler crashes on dbo.__MigrationHistory with EF-DB First

I'm having some performance issues with my MVC3-Application. That's why I decided to implement mini-profiler.
I'm using MVC3 with EF (and Razor Views). Because I'm using the DB-first approach, there is no dbo.__MigrationHistory. So how do I tell Mini-Profiler to stop looking for it?
This is what I did:
Global.asax.cs:
protected void Application_Start()
{
...
MiniProfilerEF.Initialize();
}
void Application_BeginRequest(object sender, EventArgs e)
{
...
MiniProfiler.Start();
}
protected void Application_EndRequest()
{
MiniProfiler.Stop();
}
I tried the answer in this Question, but I'm unable to use 'Database' in my DBContext (DAL).
Try this:
System.Data.Entity.Database.SetInitializer<CMDBContext>(null);
It looks like you have an existing property called Database like
public new string Database { get; set; }
in yourCMDBContext. Then when you refer to Database, you refer to that property. Since it is a property of the object, you cannot access it from static method/constructor.

Application object cannot be used in ASP.NET web page

How to use Application object in the web page?
I thought it should be something like Session object.
But when I use Application, it shows the Reference like
System.Net.Mime.MediaTypeNames.Application
Obviously, it's not the one I'm looking for.
Has it been discarded in .NET 4?
If yes, what should I use to replace the Application object.
Are you referring to this one
Page.Application Property
Gets the HttpApplicationState object for the current Web request.
<%
this.Application["test"] = "some value";
%>
inside a WebForm should work. And in the code behind it's the same story:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.Application["test"] = "some value";
}
}
The Application (HttpApplicationState) property is very much there.
Seems you have some references that are causing the confusion.
In your CS code on a Page you should be able to use it
this.Application["key"] = myObject;
It should work if you try to access it from an ASP.NET page. Application is a property of Page that returns the HttpApplicationState.
protected void Page_Load(object sender, EventArgs e)
{
if(Page.Application["Foo"] != null)
{
// ...
}
}
If you want to access it from a static context, you can use HttpContext.Current:
if (HttpContext.Current.Application["Foo"] != null){ }

How to make a ASP.NET Webforms application testable?

I am looking at a legacy enterprise application, which written using ASP.NET. No controls or web forms. This is how it works:
EmployeeList.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="EmployeeList.aspx.cs" Inherits="EmployeeList" %>
EmployeeList.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
// Security Check
// Load Template, get version 1.4 of active employee list
StringBuilder template = GetTemplate("Employee", "ActiveList", "1.4", true);
// Get list from database
using(SqlDataReader objReader = GetListFromDB())
{
while(objReader.Read())
{
//fills data
TUtils.Replace(template, ROW, "%name%", objReader[0]);
}
}
// return response
Response.Write(template.ToString());
}
private StringBuilder GetTemplate(string x, string y, string v, bool z);
{
// returns template
}
private SqlDataReader GetListFromDB() {
// returns data reader
}
My question is, since we are not using web forms, is there a way to introduce NUnit in this event driven model (as shown above)?
Also, please avoid suggestions to move to ASP.NET MVC or other patterns, which we are considering, but wondering is there any way to convert this enterprise application testable.
This is absolutely possible. You should have a look on implementing MVP pattern with ASP.NET Webforms. There are several open source implementations but you can do a smaller specialized on your your own.
The basics are to move your code behind logic to a presenterclass. The presenter class has a reference to the page implementing an interface. The trick in your case will be to Mock the Page.Response object for your test. Thats why it´s hard to unit test it right way. The PageResponse Property contains a object deriving from HttpResponseBase and that´s the baseclass you should Mock in your tests and do your asserts on with your example. You could start with that and then extend your presenter with functionalty like Session, Request etc.
If you don´t have any markup at all probably you can just create the presenter in the view constructor and don´t bother of having and reference to the view.
To clarify: The big trick is to get the code out of the aspx.cs file. That beast is not testable.
Sample base class for Presenters:
public class Presenter<T> where T : class, IView
{
protected readonly T View;
protected Presenter(T view, ILogger logger)
{
View = view;
}
public virtual void page_PreRender(object sender, EventArgs e)
{
}
public virtual void page_Init(object sender, EventArgs e)
{
}
public virtual void page_Load(object sender, EventArgs eventArgs)
{
}
public HttpContextBase HttpContext { protected get; set; }
protected HttpRequestBase Request
{
get { return HttpContext.Request; }
}
}
Since most of your code is in the code-behind, I dont think that the usual testing approach with NUnit / Visual Studio testing framework will work well.
However, I think one possible approach is to use UI Testing frameworks like WATIN / Selenium. This will enable you to still write tests for the various functionality.
I have done something similar in the past by basically writing a test case for every UI action that results in a server postback. May not be ideal but it does allow you to automate your testing.

What event do I hook into to dispose of IDisposable items in the ASP.NET *Request* cache?

Lets imagine a class
class Foo: IDisposable
{
Dispose()
{
//Dispose of nonmanged resources.
}
}
Let image that a use case exist for putting it into HttpContext.Items. It doesn't automatically raise errors when you add an object that implement IDisposable (and who knows, maybe the answer is that it should)
What event(s) do I need to hook into to dispose of that item?
Lets also assume that using blocks are not available as the object gets used into two different method blocks.
Per #Jaroslav Jandek, I think hooking into Application_EndRequest in global.asax would work just fine. You can do a simple check to see if the item is preset in HttpContext.Items and if it is then dispose of it.
protected virtual void Application_BeginRequest (Object sender, EventArgs e)
{
HttpContext.Current.Items["test"] = new IDisposableObject();
}
protected virtual void Application_EndRequest (Object sender, EventArgs e)
{
if(HttpContext.Current.Items.Contains("test")) {
((IDisposable)HttpContext.Current.Items["test"]).Dispose();
}
}

Resources