Browser history 3–trying to Nuget

This is the part 3 of 5 of my implementing of a MVC Browser history

MVC browser history – idea

Browser history –2 – implementing, small bugs

Browser history 3–trying to Nuget – modifications in order to can be transformed from an application to a component

Browser history 4–NuGet again – finally Nuget deployment

Browser history–part 5–conclusions – conclusions

TL;DR : Trying to add a feature (NuGET ) will conduce you to other features – apparently easy to implement – but took 2 hours…

 

Content:

 

First, source control is more important – http://www.joelonsoftware.com/articles/fog0000000043.html .I choose github  – deploy is a breeze with GitHub for windows . More, appharbor integration with github is awesome – you can see the application live at http://browserhistory.apphb.com/ .

 

Now , for generating Nuget package, I should be moving the classes on their own assembly / dll. Also , added this blog to the info. Ensure it works the same. Uploaded to GitHub

image

And appharbor just deployed

image

 

Now, it will be good if I let user switch implementation between memory saving  and database saving… in order to developers( that have installed the dll with  NuGet  ) switch easily to their database.

Created

BrowserUserHistoryRepositorySqlServer

and , after some implementing of IBrowserUserHistoryRepository , the method

public IBrowserUserHistoryRepository FilterByUser(string UserName)

put some problems – but solved with a private variable.

 

Now must decide the best way to switch between MemoryRepository and SqlServerRepository in

public static T AddOrRetrieveFromApplication<T>(HttpApplicationStateBase app)
where T:new()

First, we must retrieve at runtime the instance of the interface – so structuremap to the rescure.

Second, if we need to retrieve a class – must have at least a default constructor.

So the constraint of the T was gone away   – and the code is

T result;

if (typeof(T).IsInterface) {

result =(T) ObjectFactory.GetInstance(type) ;

}

else

{

result = (T)Activator.CreateInstance(type);

}

Also, in global.asax the following lines were added:

//ObjectFactory.Configure(ce => ce.For<IBrowserUserHistoryRepository>().Use<BrowserUserHistoryRepositoryMemory>());             //uncomment those for sql server ce             ObjectFactory.Configure(ce => ce.For<IBrowserUserHistoryRepository>().Use<BrowserUserHistoryRepositorySqlServer>());

Now, when deploy , AppHarbor will NOT found EntityFramework dll.

Added HintPath to csproj to find EF

<HintPath>..\packages\EntityFramework.5.0.0\lib\net40\EntityFramework.dll</HintPath>
as seen at
http://blog.appharbor.com/2012/04/24/automatic-migrations-with-entity-framework-4-3

and it works!

More, it works with sql server AppHarbor addon  and transformation of web.config.

image

 
It took 2 hours to do this thing, apparently simple.
image
Now you can find the code source on github at https://github.com/ignatandrei/MVCbrowserHistory
You can browse the application at http://browserhistory.apphb.com/

Next time: (maybe some tests and ) NuGET!

Browser history -2

This is the part 2 of 5 of my implementing of a MVC Browser history

MVC browser history – idea

Browser history –2 – implementing, small bugs

Browser history 3–trying to Nuget – modifications in order to can be transformed from an application to a component

Browser history 4–NuGet again – finally Nuget deployment

Browser history–part 5–conclusions – conclusions

Now we repair the important issues and make some GUI adjustements to be nicer to the user GUI.

  1. Why the history does not display?
    • Because OnResultExecuted  is executed AFTER the View that display the results  is executed
    • Fix: do not display the ones that have no title. Modified ViewModel to take an IEnumerable.
  2. Why the count does not display after 2 clicks?
    • Because it was not saved in BrowserUserHistoryRepositoryMemory – only after SaveToRepositoryInterval links number
    • Fix: In the action save again to have latest clicks. Also modified interface Save to take an IEnumerable – and not a class.
  3. Modified GUI interface to have links where the URL displays – add ViewUrl shared VIew in MVC.
  4. Add numbering to the table ( 1,2,…)
  5. Add texts ( instead of My MVC application – My Browser History application)
  6. Add Filter By User – to be easier for the programmers that will use the program.
  7. Maybe will be useful to add sorting and filtering   – but only if someone asks.

The code is here

MVC browser history

This is the part 5 of 5 of my implementing of a MVC Browser history

MVC browser history – idea

Browser history –2 – implementing, small bugs

Browser history 3–trying to Nuget – modifications in order to can be transformed from an application to a component

Browser history 4–NuGet again – finally Nuget deployment

Browser history–part 5–conclusions – conclusions

I want to do another small open source utilities project – MVC browser history . That seems simple at the beginning – but , yet , there are small tasks to do that are not so easy .

What does MVC browser history  does? Well, keep an history of the links the user clicks through an MVC site. I must eliminate the ajax requests and Child requests – so keep the just the URL’s

So what I have learned after one hour:

Thinking process :

I must somehow maintain the url’s – either in database , either in memory – so a Repository concept came handy.

Data to be saved includes :

  1. URL –easy –  HttpContext.Request.Url.ToString();
  2. Date – easy – DateTime.Now;
  3. UserName – not so easy – what if user not registered?
  4. PageName – it should belong to that, but, from a RelationalDatabase in a 3rd form, should be another table.

Named this class BrowserUserHistoryData ( rather a long name, but descriptive)

Now detailing:
URL – possible problem : differentiate between Person/Edit/1 and Person/Edit/2. It’s a feature, not a bug Winking smile : browser history, not Action history. More, the User can have acces to Person/Edit/1 and NOT Person/Edit/2.
UserName – maybe Session , if not registered? (con.User.Identity.IsAuthenticated ? con.User.Identity.Name : con.Session.SessionID); , if not WebApp, then … ok, not for this time.

How to obtain the data? The global filter from http://bradwilson.typepad.com/blog/2010/07/aspnet-mvc-filters-and-statefulness.html

What to obtain ? A user history and first 5 links order by count

Programming:

Errors repaired:

  1. Brad Wilson put data in context.HttpContext.Items . Forget that is good for one request only. Thinking about how to persist and obtain data in MVC action and Global filter- and storing to Application . Made public static T AddOrRetrieveFromApplication
  2. Adding ViewName in OnResultExecuting, not in OnResultExecuted.
  3. Reading data from Repository WITHOUT persisting there Winking smile.
  4. Thinking that the Model of the page is just the list of user history. Nope, it is also the first 5 links order by count : HistoryViewModel
    public class HistoryViewModel
        {
            public BrowserUserHistory UserHis;
            public IBrowserUserHistoryRepository rep;
        }
    

Errors not repaired:

  1. Not showing just HIS user browser history, but all ( not to be repaired, since Cassini changes session_id all the time) . NOT TO BE REPAIRED.
  2. Latest links, history himself, not show view name

image

What I have enjoyed:

  1. Programming process
  2. The idea that will be useful to other people
  3. Linq:  – can be translated to database also.
     public IEnumerable<KeyValuePair<string,int>> MostUsed(int Count, DateTime? date)
            {
                var data= historyMemory.Where(item =>(date==null || item.Date.Subtract(date.Value).Days == 0)).GroupBy(item=>item.Url).OrderByDescending(g=>g.Count()).Take(Count);
                return data.Select(i =>new KeyValuePair<string,int>( i.Key,i.Count()));
            }
    

What to do next:

  1. Correct the error
  2. Test more the application with a real application
  3. Make the application understandable – comments.
  4. Make the application publicly available
  5. Spread the word ( already did, but not enough).

Code can be downloaded from BrowserHistory

. Play with it – and, if you like, drop a comment.

.TT files and property names

This is the second post of http://msprogrammer.serviciipeweb.ro/2012/07/09/tt-files/

Now I will show how .tt files helps you for sorting .

In many WebInterfaces you do present to the user an array of items – a list – and the user can sort after various fields. Let’s make an example:

You have an EmployeeViewModel class that have FirstName, LastName and DepartmentName ( take note that is an EmployeeViewModel that must show to the user the Department name too – and is not the Employee class that have a reference to the table Employee).

Usually, for loading easily the EmployeeViewModel you do create a view in database with the same columns as the names of the properties (FirstName, LastName and DepartmentName)

Now, how you sort after FirstName, LastName and DepartmentName  WITHOUT hardcoding the strings ?( Why hardcoding is not good: the modification are not catch at compile time, but at runtime – and can be hidden)

.TT files to the rescue:

Starting of this class

 

public partial class EmployeeViewModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string DepartmentName { get; set; }
        
    }

I generate , with classFieldNames.tt , this:

 

public partial class EmployeeViewModel
						{
        public static FieldNames fieldNames= new FieldNames();
        public class FieldNames{
								
                public  string FirstName ="FirstName";
                public  string LastName ="LastName";
                public  string DepartmentName ="DepartmentName";
		}													
        }

And now in the code is that:

 

 var field = EmployeeViewModel.fieldNames.DepartmentName;
            Console.WriteLine(field);

this is the code for TT_FieldNames. Enjoy!

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.