0

MCV5 My Razor model type is: IOrderedEnumerable

I cannot figure out how to post back to the controller. If I use a regular ViewModel class it works fine, but as I have a Header/Detail on my Razor page, when I try to post back, as IOrderedEnumerable, an error is instantly generated and I cannot figure out how to post back...

My ViewModel:

public class DocumentViewModel
{
    [Display(Name = "Repostitory")]
    public string Repository { get; set; }
    public int DocId { get; set; }
    [Display(Name = "Statement Date")]
    public DateTime DocDate { get; set; }

    [Display(Name = "Account Number")]
    public string AcctNum {get;set;}
    public string FND { get; set; }
    public string strURL { get; set; }
    public int UserID { get; set; }

}

My code to populate the header/detail of the view model:

{
    ViewBag.dropdownMonths = new SelectList(db.vDDLMonths.ToList(), "codeID", "codeText","0");
    ViewBag.dropdownYears = new SelectList(db.vDDLYears.ToList(), "codeID", "codeText","2016");
    ViewBag.UserId = Convert.ToString(model.userID);
    //Generate Querystring 
    //Pull Account List
    string strQSAccountList = (from u in db.vUserParticipantQS
                               where u.userID == model.userID
                               select u.AccountNumbersList).FirstOrDefault();

    string strQueryString = BuildQueryString("List");
    string strMonth = "0";
    string strYear = "2016";
    string strStartDate = strYear;
    string strEndDate = strYear;

    int intMonth = 0;

    if (int.TryParse(strMonth, out intMonth))
    {
        if (intMonth > 0)
        {
            strStartDate += strMonth;
            strEndDate = strStartDate;
        }
        else
        {
            strStartDate += "01";
            strEndDate += "12";
        }
    }
    //Pull Months  based on 
    strQueryString = strQueryString + "&BYM=" + strStartDate + "&EYM=" + strEndDate + "&A=" + strQSAccountList;

    string newURL = BuildEncryptedURLRequest(strQueryString);
    List<DocumentViewModel> docs = new List<DocumentViewModel>();
    docs = XMLBuild.CreateXML(newURL, model.userID);

    //Group results (for display in Razor view)
    var queryAcct =
        from doc in docs
        group doc by doc.AcctNum into AcctGroup
        orderby AcctGroup.Key
        select AcctGroup;

    return View("~/Views/Statements/Docs.cshtml", queryAcct);// This passes a type of IOrderedEnumerable<IGrouping<string, AodNetIntegration.Models.DocumentViewModel>>

}


public static List<DocumentViewModel> CreateXML(string newURL,  int UserID)
{
    XmlDocument docXML = new XmlDocument();
    docXML.Load(newURL);

    XmlNodeList nodes = docXML.DocumentElement.SelectNodes("/page/ALCHEMY/DOC");

    List<DocumentViewModel> docs = new List<DocumentViewModel>();
    int Id = 0;
    DateTime dt;
    string qs = "";
    string url = "";
    string docDate="";
    foreach (XmlNode node in nodes)
    {
        DocumentViewModel doc = new DocumentViewModel();

        doc.Repository = node.SelectSingleNode("REPOSITORY").InnerText;
        if (int.TryParse(node.SelectSingleNode("DOC_ID").InnerText, out Id))
            doc.DocId = Id;
        if (DateTime.TryParse(node.SelectSingleNode("DOC_DATE").InnerText, out dt))
        {
            doc.DocDate = dt;
            docDate = dt.ToString("MM/dd/yyyy");
        }

        doc.AcctNum = node.SelectSingleNode("A").InnerText; //node.Attributes["id"].Value;
        doc.FND = node.SelectSingleNode("FND").InnerText;
        doc.UserID = UserID;
        //create direct link for each statement
        qs = BuildQueryString("Document") + "&A=" + doc.AcctNum + "&DTE=" + docDate; //A=ACG473&DTE=07/31/2016;
        url = BuildEncryptedURLRequest(qs);
        doc.strURL = url;
        docs.Add(doc);
    }

    Debug.WriteLine("Total docs: " + docs.Count);
    docs.OrderBy(o => o.AcctNum)
        .ThenBy(o => o.DocDate);

    List<DocumentViewModel> docAccts = new List<DocumentViewModel>();

    return docs;
}

Model code:

    @model IOrderedEnumerable<IGrouping<string, AodNetIntegration.Models.DocumentViewModel>>

    @using (Html.BeginForm("GetStatement", "Statements", new { ReturnUrl  = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))

{
    @Html.AntiForgeryToken()
    @Html.DropDownList("dropdownMonths",null, new { style = "width: 200px;" })
    @Html.DropDownList("dropdownYears", null, new { style = "width: 200px;" })

    <input type="submit" value="GO" class="btn btn-default" /> @*Post "GO" button that does not work!!*@


        <div id="detailsDiv">
            @foreach (var AccountGroup in Model )
            {
                <p><h1>@AccountGroup.Key</h1></p>
                foreach (var item in AccountGroup)
                {
                    <p>
                        @*@Html.ActionLink(@item.DocDate.ToShortDateString(), "GetStatement", "Statements", new {id= @ViewBag.UserID, statementDate = @item.DocDate.ToShortDateString(), acctNumber = AccountGroup.Key.ToString() }, new { @class = "form-control, col-sm-6,  medwidth" })
                        @Html.ActionLink("View", "ViewPDF", new { target = @item.strURL })*@
                        <a href="@item.strURL.ToString()" target="_blank">@item.DocDate.ToString("MMM yyyy") Statement</a>
                    </p>
                }
            }       
         </div>

My "Statements/GetStatement" controller (returned from this view) -- This does not get recognized!!

    public ActionResult GetStatement(IOrderedEnumerable<IGrouping<string, AodNetIntegration.Models.DocumentViewModel>> model, string returnUrl)
    {//DO Stuff
    }

My GO button does not call the Controller Method unless I change it to a regular model... is there a way to return > to the controller by posting the page? If not, what is the best way to do this. I would like to do this via AJAX also so I can do a partial post, but it seems I have to figure the posting out first. I've looked at this and this, but cannot quite figure out what I'm missing! Thanks!

Community
  • 1
  • 1
Danimal111
  • 1,976
  • 25
  • 31
  • What controller method? And what do you mean _post back as IOrderedEnumerable_? The only form controls you have are 2 ` –  Nov 21 '16 at 21:24
  • @StephenMuecke - I just added the second controller (that my view is supposed to return to "StatementsController GetStatement method) - sorry for the confusion... – Danimal111 Nov 21 '16 at 21:37
  • I assumed that's marked `[HttpPost]`? Remove the first `IOrderedEnumerable<...> model` parameter - your parameters should be `string dropdownMonths` and `string dropdownYears` to match the form controls (your not sending anything related to `IOrderedEnumerable.....` (which would not work anyway - you cannot bind to interfaces) –  Nov 21 '16 at 21:41
  • I don't know if that's viable, the model binder shouldn't be able to bind interfaces because it doesn't know what class it is backed by, why are you even trying to do that, post a list and sort and group it after its back on the server – johnny 5 Nov 21 '16 at 21:42
  • @johnny5 - Can you post how to "post a list and sort and group it after its back on the server"?I am able to show the results on the Razor view based on the "varQuery" (which works great with the header/detail info. I couldn't figure out another way to do it (been at it all day). – Danimal111 Nov 21 '16 at 21:45
  • Also you need to keep in mind that just because something starts in a structure, and you have access to it when coding, this does not translate back to the client, the client does not have the information on what you were grouped by originally, even if it did, on your http post you would also need to specify that. If you really need to you can post back a dictionary of lists. which is should be equivalent to your structure, you can look up by key and then you have a list of data associated with it – johnny 5 Nov 21 '16 at 21:46
  • Make your model a Dictionary of Lists, Change the default JSON Contract resolver to use newtonsoft json deserialize, which will make dictionaries work better without playing with the ajax response to much. Then you just have to follow the approiate json structure { key:'somestring', value: [1, 2, 3] } – johnny 5 Nov 21 '16 at 21:49
  • @johnny5 - Thanks for this... Could you please post a little code... been at this all day and my head is spinning slightly... – Danimal111 Nov 21 '16 at 21:50
  • I'm in a meeting I can't post much but I'll give you some links[Changing the default json serializer] ( http://stackoverflow.com/questions/13274625/how-to-set-custom-jsonserializersettings-for-json-net-in-mvc-4-web-api) – johnny 5 Nov 21 '16 at 21:52
  • 1
    Controller: `public ActionResult GetStatement(Dictionary> model, string returnUrl) { }` – johnny 5 Nov 21 '16 at 21:54
  • If your posting from ajax i believe the structure should be like this { key:'somekey', value: [1, 2, 3], } maybe caps Key Value to bind – johnny 5 Nov 21 '16 at 21:59

0 Answers0