0

I am using ASP.NET MVC 4 and I have a View where I can see a few rows (expenses) and I have a checkbox inputs beside each row. There is a Boolean property called "Submitted" and a DateTime property called DateSubmitted in the model.

I have a method called SubmitExpenses() and I only want the rows that are 'checked' to be updated.

The columns that would be updated are DateSubmitted and Submitted.

Here is my model:

public class Expense
{
    public Expense() { }

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ExpenseId { get; set; }

    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    [Display(Name = "Date Submitted")]
    public DateTime? DateSubmitted { get; set; }

    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    [Display(Name = "Expense Date")]
    public DateTime? ExpenseDate { get; set; }

    [Display(Name = "Submitted?")]
    public bool Submitted { get; set; }

    [Required]
    [Display(Name = "Name")]
    public int UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual UserProfile UserProfile { get; set; }

}

Here is the SubmitExpenses() method:

public ActionResult SubmitExpenses(List<Expense> expenses, DateTime? expenseDate = null, DateTime? expenseDate2 = null, int? userId = 0)
{
    expenseDate = (DateTime)Session["FirstDate"];
    expenseDate2 = (DateTime)Session["SecondDate"];

    if (expenseDate == null || expenseDate2 == null)
    {
        expenseDate = DateTime.Now.AddMonths(-1);
        expenseDate2 = DateTime.Today;
    }

    string currentUserId = User.Identity.Name;

    var query = from e in db.Expenses
                join user in db.UserProfiles on e.UserId equals user.UserId
                where user.UserName == currentUserId && (e.ExpenseDate >= expenseDate && e.ExpenseDate <= expenseDate2) && e.DateSubmitted == null
                orderby e.ExpenseDate descending
                select e;

    if (User.IsInRole("admin") && userId != 0)
    {

        query = from e in db.Expenses
                join user in db.UserProfiles on e.UserId equals user.UserId
                where user.UserId == userId && e.ExpenseDate >= expenseDate && e.ExpenseDate <= expenseDate2 && e.DateSubmitted == null
                orderby e.ExpenseDate descending
                select e;
    }
    else if (User.IsInRole("admin"))
    {
        query = from e in db.Expenses
                join user in db.UserProfiles on e.UserId equals user.UserId
                where e.ExpenseDate >= expenseDate && e.ExpenseDate <= expenseDate2 && e.DateSubmitted == null
                orderby e.ExpenseDate descending
                select e;
    }


    foreach (Expense exp in query)
    {
        exp.DateSubmitted = DateTime.Today;
    }

    try
    {
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return RedirectToAction("Submit");
    }

}

Here is the View:

<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.DateSubmitted)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ExpenseDate)
        </th>

        @if (User.IsInRole("admin"))
        {
            <th>
                @Html.DisplayNameFor(model => model.UserProfile.UserName)
            </th>
        }
        <th></th>
    </tr>
    <tr>
        <td>
            <b>Select All:</b>
            <br />
            <input type="checkbox" name="expense" value="Expense" id="selectAllCheckboxes" class="expenseCheck">
        </td>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td class="submitCheck">
                @Html.DisplayFor(modelItem => item.Submitted)
            </td>

            <td>
                @Html.DisplayFor(modelItem => item.DateSubmitted)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ExpenseDate)
            </td>

            @if (User.IsInRole("admin"))
            {
                <td>
                    @Html.DisplayFor(modelItem => item.UserProfile.UserName)
                </td>
            }
        </tr>
    }

</table>

 @Html.ActionLink("Submit Expenses", "SubmitExpenses")

 @section scripts {
<script type="text/javascript">


    $("#selectAllCheckboxes").click(function () {
        $('.submitCheck input:checkbox').not(this).prop('checked', this.checked);
    });

    $('.submitCheck input:checkbox').prop('disabled', false);


</script>

}

I know how to submit all expenses that are in the date range specified (or all expenses that are showing in the view), but I'm not sure how I would update each row for only the rows that are checked.

Thank you.

1 Answer 1

1

First, as an aside, you can use query composition instead of repeating your query each time:

var query = from e in db.Expenses
            join user in db.UserProfiles on e.UserId equals user.UserId
            where e.ExpenseDate >= expenseDate && e.ExpenseDate <= expenseDate2 && e.DateSubmitted == null
            orderby e.ExpenseDate descending
            select new { e, user };

if (User.IsInRole("admin") && userId != 0)
{
    query = query.Where(x => x.user.UserId == userId);
}
else if (!User.IsInRole("admin"))
{
    query = query.Where(x => x.user.UserName == currentUserId);
}

Now for the question: If I understand you correctly you want to filter out the Expenses from the database that were marked as Submitted in the view. These filtered expenses should be updated. A way to do that is by joining the database expenses with the ones from the view:

var joined = from dbExpense in query.Select(x => x.e).AsEnumerable()
             join localExpense in expenses on dbExpense.ExpenseId equals localExpense.ExpenseId
             where localExpense.Submitted
             select dbExpense;

foreach (Expense exp in joined)
{
    exp.DateSubmitted = DateTime.Today;
}

By using AsEnumerable on the database query, you can join it with a local sequence (expenses) as LINQ to objects.

Sign up to request clarification or add additional context in comments.

10 Comments

Thank you for the style tips. I didn't know I could shorten my code like that! I was just wondering where the 'e' in 'x.e' comes from.
From new { e, user }.
The 'joined' variable is coming back as null. Is there anything I need to do in the view to get variable to be set?
joined is null? I can't imagine that, because the result of a LINQ query returning an enumerable is never null. Or is it empty?
Isn't expenses null?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.