views:

916

answers:

4

Hello, I am trying to figure out how to do the following:

1) After a form is submitted, serialize the raw post data and store it to a database

2) Read the post data from the db and replay it by re-posting it to the same URL

To explain my end goal, we have three main envs: dev, acceptance, and production. I would like to be able to make a change in dev and then promote that change to acceptance by doing an identical post.

Anybody have any ideas?

Thanks, Paul

+1  A: 

This is really roundabout way of moving data from one environment to another. You should be using fixtures in the form of XML, JSON, or SQL queries to move data from one environment to another. This process can be further automated using some simple scripts.

If this happens a lot, you should look into proper database replication.

Regardless, using the form is a really silly way of doing things, just do it all in the backend and have your databases talk directly to each other.

Soviut
I think he is saying he wants to use the same post he did in dev in the other environments to test, not to move data. Although I might be reading this wrong.
JoshBerke
Why is he "testing" on a production environment? That's what the dev and staging environments are specifically designed for. He said he's trying to "promote" the change to a different environment.
Soviut
I know you can read the question either way he is not being specific enough. If he's actually pushing a change to his production environment then I'd aggree he shouldn't be doing this.
JoshBerke
Thank you very much for the responses. I am looking to move updates to a new env. It is correct that is somewhat roundabout and we have methods for promoting SQL statements.However, when these updates are posted to the given environment also trigger other actions (restarting or refreshing various apps).
A: 

First thing is to get the request, you can do this by creating a new http module which you can then turn on or off via the config file.

Find a place in the request lifecycle where you'd like to save the message (Maybee in BeginRequest), and you'll want to record the following:

  • Request.InputStream
  • Url
  • User Information (If your going to be dealing with authentication)

On the flip side when your ready to post the data, you'll want to find a method that will let you just repost the binary data that you pulled from the Request.InputStream. Off the top of my head I'm not sure if there is a class in .net which will help with this. But one of the web clients might have a method to allow you to specify the entire body of the request.

JoshBerke
+3  A: 

I did something similar once for logging purposes. I logged both GET and POST requests such that they could be duplicated, for the purposes of tracking down errors logged by our test group, and by the live application.

The biggest trick here is that your web application needs to be, for the most part, stateless. If you pass information around your application with Sessoin or use ViewState at all in your application, you may hit a few more bumps.

If you've created your website to be RESTful though, this shouldn't be too hard. And, by RESTful (http://en.wikipedia.org/wiki/Restful) I refer to the fact that any given RESTful request makes no assumptions about previous requests made against the server - they are atomic in of themselves, and include all necessary information to perform whatever action they are trying to perform.

I accomplished this by doing the following:

1) I created ActionFilters on the actions that I wanted to monitor. These ActionFilters performed the capture of the POST data and saved it to the database. This worked well because it was less invasive in the code, and could easily be added/removed to any action I was interested in.

2) The ActionFilter essentially logged the request type (GET vs. POST, via HttpContext.Current.Request.HttpMethod if I recall correctly) and the URL the request mas made against. If it was a POST, I serialized the Form data (HttpContext.Current.Request.Form) into JSON. I chose JSON because it was human readable (important for helping diagnose problems, which was the purpose of this for me), and since you're working with FORM data it's flat enough to easily serialize into a nice flat JSON structure. I believe I also logged all of the other request variables as well (HttpContext.Current.Request.Headers) for information purposes, though depending on your needs that may be superfluous.

I used System.Web.Script.Serialization.JavaScriptSerializer to serialize the form data.

All this data was stored in a database (request type, URL, serialized post data, timestamp, current user, etc.)

3) I created a new MVC controller specifically designed for viewing and re-invoking the requests. In my case, it was LoggingController, since I was logging the requests for monitoring. My primary view was a list of all requests made and the target URL. If I drilled down and did a "view"/"show" of a specific entry, it would show me all of the details I logged.

The actual duplication of the action was created by deserializing the JSON data and constructing (in my case hidden) form fields that were populated on the "view" page with the deserialized data. I then added a button - Green for GETs and red for POSTs. Clicking the button would duplicate the action - GET's are easy, you just send the user to the target page.

However, for POSTs, I used a JavaScript that alerted the user "You are about to duplicate a POST request, which may modify data on the server depending on the action being invoked (deletions, updates, etc). Continue?"

If they clicked yes, it submitted the form w/ JavaScript, making it a POST action, and, wala, duplicated actions.

In your case, you would be logging the data from one of your environments, and then copying said data over to your other environments database so you could load up your equivalent of my "LoggingController" and fire off whichever actions you want to duplicate.

And, obviously, you can take this as far as you want. You could use your "recorded" data to drive some unit tests, etc.

Matt
Thank you for the great details. It is very much appreciated.
A: 

I can hardly thing of an application that can be fully automated this way.

You could try it with out of the box products that support record and replay like:

Jmeter, Selenium, IOpus or to some degree Fiddler. IOpus is the easiest to start with.

You will soon see that this is the hard way of doing things and maybe save you the trouble of implementing your own record/replay solution.

Malcolm Frexner