问题描述:

I want to count how many times a user watches a Product.

Product has ViewCount property in integer type, in the Details view, I increase ViewCount :

public ActionResult Details( int id )

{

...

product.ViewCount = product.ViewCount + 1;

db.SaveChanges();

return View( product );

}

But in every refresh, ViewCount increases.

What should I do that ViewCount increases 1 time in every session of user?

Or other way, right tag, any link, please.

网友答案:

You can use cookie.

var productId = 1;


if (Request.Cookies["ViewedPage"] != null)
{
    if (Request.Cookies["ViewedPage"][string.Format("pId_{0}",productId )] == null)
    {
        HttpCookie cookie = (HttpCookie)Request.Cookies["ViewedPage"];
        cookie[string.Format("pId_{0}",productId )] = "1";
        cookie.Expires = DateTime.Now.AddDays(1);
        Response.Cookies.Add(cookie); 

        db.Execute("UPDATE Products SET ViewCount = ViewCount + 1 WHERE ProductId = @id", new { id = productId } ); 
        db.SaveChanges();
    }
}
else
{
    HttpCookie cookie = new HttpCookie("ViewedPage");
    cookie[string.Format("pId_{0}",productId )] = "1";
    cookie.Expires = DateTime.Now.AddDays(1);
    Response.Cookies.Add(cookie); 

    db.Execute("UPDATE Products SET ViewCount = ViewCount + 1 WHERE ProductId = @id", new { id = productId } ); 
    db.SaveChanges();
}
网友答案:

I would suggest you to create some action filter to track it.

public class TrackFilter: IResultFilter
{
  public void OnResultExecuting(ResultExecutingContext filterContext)
  {

  }

  public void OnResultExecuted(ResultExecutedContext filterContext)
  {
    // do a database call and update the count
  }
}

[Track]
public ActionResult Details(int id)
{
}

You can refer this thread also for more idea.

网友答案:

Your code is not thread-safe: if two users access the page simultaneously then the ViewCount will be incremented by 1 instead of 2 (because the value is incremented by the DB consumer rather than the DB itself). You can solve this by running the SQL UPDATE Products SET ViewCount = ViewCount + 1 WHERE ProductId = @id directly. Your DBMS will provide concurrency protection.

Anyway, to prevent the view count from being incremented by additional views in the same session just use a hashset stored in session, like so:

public ActionResult Details(Int32 id ) {

    HashSet<Int32> productsSeen = (HashSet<Int32>)Session["ProductsSeen"];
    if( productsSeen == null ) {
        Session["ProductsSeen"] = productsSeen = new HashSet<Int32>();
    }

    if( !productsSeen.Contains( id ) ) {

        db.Execute("UPDATE Products SET ViewCount = ViewCount + 1 WHERE ProductId = @id", new { id = id } ); // psuedocode. This isn't a real EF construct.
        db.SaveChanges();
    }

    return View( product );
}
网友答案:
model.ViewCount = model.ViewCount + 1;

_context.Entry(model);

_context.SaveChanges();

return View(model);
相关阅读:
Top