Not even sure this is possible, thought it would be very nice to have though.
I have created a sales page, with a view component of outstanding quote requests.
@{
ViewData["Title"] = "Sales Page";
}<h2>Shenton Application - Sales Team</h2>
To start a sale first select Quote Request
<h2><a asp-area="" asp-controller="QuoteRequests" asp-action="SalesCreate">Quote Request</a></h2><h4> Quote Requests Not Quoted</h4><div>@await Component.InvokeAsync("QuoteRequests")</div><h4>Quotes To Follow Up</h4>
All fine and dandy.
Then I thought hold on wouldn't it be nice if I can sort the quote requests and maybe there will be more than a few outstanding, I hope not, but should build it in, just in case, and then whilst I am at it lets add search as well. Cant think why, but I
guess a contact may call up and we may want to search his request out to update it or something.
The code I added to view component is:
public IViewComponentResult Invoke(
string sortOrder,
string currentFilter,
string searchString,
int? page)
{
ViewData["QRSortParm"] = sortOrder;
ViewData["CloseDateSortParm"] = String.IsNullOrEmpty(sortOrder) ? "close_desc" : "";
ViewData["RequestSortParm"] = sortOrder == "Request" ? "request_desc" : "Request";
ViewData["QDSortParm"] = sortOrder == "QD" ? "qd_desc" : "QD";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewData["CurrentFilter"] = searchString;
var quoteRequests = from q in _context.QuoteRequest
.Where(q=>q.Quoted==false)
select q;
if (!String.IsNullOrEmpty(searchString))
{
quoteRequests = quoteRequests.Where(q => q.Requested.Contains(searchString));
}
switch (sortOrder)
{
case "close_desc":
quoteRequests = quoteRequests.OrderByDescending(q => q.CloseDate);
break;
case "request_desc":
quoteRequests = quoteRequests.OrderByDescending(q => q.Requested);
break;
case "Request":
quoteRequests = quoteRequests.OrderBy(q => q.Requested);
break;
case "qd_desc":
quoteRequests = quoteRequests.OrderByDescending(q => q.QDescription);
break;
case "QD":
quoteRequests = quoteRequests.OrderBy(q => q.QDescription);
break;
default:
quoteRequests = quoteRequests.OrderBy(q => q.CloseDate);
break;
}
//return View(quoteRequests);
int pageSize = 7;
return View(PaginatedList<QuoteRequest>.CreateAsync(page ?? 1, quoteRequests.AsNoTracking(), pageSize));
}
normally I have async PaginatedList, but this didn't like it, so I took the async out.
Then in default view I have:
@model PaginatedList<Eva804.Models.QuoteRequest><form asp-action="Index" method="get"><div class="form-actions no-color"><p>
Find by Requested: <input type="text" name="SearchString" value="@ViewData["currentFilter"]" /><input type="submit" value="Search" class="btn btn-default" /><a asp-action="Index">Back to list</a></p></div></form><table class="table"><tr><th><a asp-action="Index" asp-route-sortOrder="@ViewBag.CloseDateSortParm" asp-route-currentFilter="@ViewData["CurrentFilter"]">Closing Date</a></th><th><a asp-action="Index" asp-route-sortOrder="@ViewBag.RequestSortParm" asp-route-currentFilter="@ViewData["CurrentFilter"]">Requested By</a></th><th>
Contact Detail</th><th><a asp-action="Index" asp-route-sortOrder="@ViewBag.QDSortParm" asp-route-currentFilter="@ViewData["CurrentFilter"]"> Quote Description</a></th><th></th></tr>
@foreach (var q in Model)
{
<tr><td>
@q.CloseDate</td><td>
@q.Requested
</td><td>
@q.ConDetail</td><td>
@q.QDescription.Substring(0, Math.Min(q.QDescription.Length, 28))</td><td><a asp-controller="QuoteRequests"
asp-action="Details"
asp-route-id="@q.QuoteRequestID">Details</a> |<a asp-controller="Quotes"
asp-action="Create"
asp-route-id="@q.QuoteRequestID">Quote</a></td></tr>
}
</table>
@{
var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.HasNextPage ? "disabled" : "";
}<a asp-action="Index"
asp-route-page="@(Model.PageIndex-1)"
class="btn btn-default @prevDisabled btn">
Previous</a><a asp-action="Index"
asp-route-page="@(Model.PageIndex+1)"
class="btn btn-default @nextDisabled btn">
Next</a>
Nothing wrong in here I can see. Same code I use elsewhere for searching, sorting and paging. All good I thought.
However when I click on the sales index in IE it is creating an error message:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Threading.Tasks.Task`1[Eva804.PaginatedList`1[Eva804.Models.QuoteRequest]]', but this ViewDataDictionary instance requires a model item of type 'Eva804.PaginatedList`1[Eva804.Models.QuoteRequest]'.
Which to me makes no sense.
Why is it telling me about Systems Threading Tasks when neither the ViewComponent or the Default list it as a using item?
Why is it throwing this error at all?
Is this fixable or am I asking too much from the view component?