0

I'm stuck on a problem trying to get a foreach block of code to work within an mvc controller and viewmodel.

What i'm trying to achieve is loop through the datetime values and if less than 60 seconds, show seconds. if more than 60 seconds but less than 1 hour show minutes. else show full datetime.

I can get the above to work, but it only displays the 1st record. I have tried putting foreach loops in various places but just cannot seem to get it to work.

Would appreciated a fresh pair off eyes to help with this.

public class MostRecentPostsViewModel
    {
        public List<MembersForumProperties> SelectMostRecentForumPosts { get; set; }
        public string DateAndTimeOfForumPosts                          { get; set; }
    }

    public class IsPostLessThanOneHour
    {
        public static string DisplayPostInMinutesOrSeconds(string displyMostRecentForumPosts)
        {
            string displayTime = string.Empty;

            //foreach (var postTime in mv.SelectMostRecentForumPosts)
            //{
            //    dte = postTime.ForumMemberDateTimePostedPost;
            //}

            DateTime dtn = DateTime.Now;
            DateTime timeOfPost = Convert.ToDateTime(displyMostRecentForumPosts);

            TimeSpan ts = dtn - timeOfPost;
            if (ts.TotalSeconds > 0 && ts.TotalSeconds < 60)
            {
                displayTime = "about " + ts.Seconds + " seconds ago";
            }
            else if (ts.TotalSeconds > 61 && ts.TotalSeconds < 3600)
            {
                displayTime = "about " + ts.Minutes + " minutes ago";
            }
            else
            {
                displayTime = displyMostRecentForumPosts;
            }
            return displayTime;
        }
    }

Controller

public PartialViewResult MostRecentMembersPosts()
        {
            var displyMostRecentForumPosts = _imf.DisplayMostRecentForumPosts().ToList();
            var loopThroughDateTimes       = displyMostRecentForumPosts.ToList();
            var test = "";
            foreach (MembersForumProperties t in loopThroughDateTimes)
            {
                test = t.ForumMemberDateTimePostedPost;
            }

            var membersMostRecentPost = new MostRecentPostsViewModel
            {
              SelectMostRecentForumPosts = displyMostRecentForumPosts,

              DateAndTimeOfForumPosts = IsPostLessThanOneHour.DisplayPostInMinutesOrSeconds(test)
            };

            return PartialView("pvMostRecentMembersPost",membersMostRecentPost);
        }
4
  • Is the code that comments out the foreach loop purposeful? Commented Oct 22, 2013 at 11:50
  • Hi George, The commented out code for the foreach loop was a previous attempt, just have not deleted it Commented Oct 22, 2013 at 11:53
  • If I'm reading this right, you want to return the most recent timestamp from a user's postings? If so, I think you might want to re-engineer this. Call the DB with a query that returns the most recent post timestamp by applying MAX and filtering by the author. Then run your logic on the return value to display the appropriate message. Commented Oct 22, 2013 at 11:54
  • Hi Chris, no the dates will be from various users to post a comment on the forum, if they post the comment within 60 seconds, it will display something like posted 24 seconds ago or if over 60 second posted 4 minutes ago Commented Oct 22, 2013 at 11:57

1 Answer 1

2

Why not just send the dates down as is and use a JS plugin like TimeAgo e.g.

public PartialViewResult MostRecentMembersPosts()
{
    return PartialView("pvMostRecentMembersPost", _imf.DisplayMostRecentForumPosts().ToList());
}

Then in your view

@model IEnumerable<MemberForumProperties>

<!-- Head section would need to be defined in your master page first -->
@section Head {
    <script src="jquery.timeago.js" type="text/javascript"></script>
    <script type="text/javascript">
        $.ready(function() {
            $("abbr.timeago").timeago();
        });
    </script>
}

@foreach (var m in Model)
{
    <abbr class="timeago" title='@m.ForumMemberDateTimePostedPost.ToString("s")' />   
}

TimeAgo will take care of converting your DateTime values into a fuzzy timestamp.


The Problem

If you don't want to go for the client-side approach, then to fix your current server-side issue you need to send down a list of relative times, at the minute you only appear to be sending down the last relative time i.e.

var test = "";
foreach (MembersForumProperties t in loopThroughDateTimes)
{
    test = t.ForumMemberDateTimePostedPost;
}
// test now contains the date/time of the last item in the `loopThroughDateTimes` list

var membersMostRecentPost = new MostRecentPostsViewModel
{
    SelectMostRecentForumPosts = displyMostRecentForumPosts,

    DateAndTimeOfForumPosts = IsPostLessThanOneHour.DisplayPostInMinutesOrSeconds(test)
};
// DateAndTimeOfForumPosts only contains the relative string for the last date/time

Your current setup just appears a bit messy & cluttered and not very readable.

The Solution

To tidy it up a bit here's what I would do

public static class DateTimeExt
{
    public static string ToRelativeTime(this DateTime value)
    {
        // you could move the entire implementation of `DisplayPostInMinutesOrSeconds` to here
        return IsPostLessThanOneHour.DisplayPostInMinutesOrSeconds(value);
    }
}
...

public PartialViewResult MostRecentMembersPosts()
{
    return PartialView("pvMostRecentMembersPost", _imf.DisplayMostRecentForumPosts().ToList());
}

And then in your view

@model IEnumerable<MemberForumProperties>

@foreach (var props in Model)
{
    <p>@props.ForumMemberDateTimePostedPost.ToRelativeTime()</p>   
}
Sign up to request clarification or add additional context in comments.

5 Comments

This answer would be greatly improved by actually showing the OP how to apply that plugin to his particular problem, perhaps with an example. As it stands, this answer risks being flagged and deleted because it is not a very good answer, it just points the user somewhere else without addressing their particular issue.
@GeorgeStocker sure will update. However, the link does go to the documentation which is effectively self explanatory.
What happens if the link dies or the documentation moves? That's part of the reason we frown upon answers that are effectively just links. As it stands, you've turned your answer into a really good answer by including what we need to solve the user's issue here.
Hi James thanks, never heard of that, will use it, but I really want to work out how to solve my problem server side, so if I ever get this problem again, i will know how to solve it.
@James thanks for code and jquery code, your server side was more readable, the joys of learning :-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.