根据ASP.NET MVC中的复选框选择填充模型的嵌套列表对象

时间:2014-05-21 18:21:00

标签: c# asp.net post asp.net-mvc-5 razor-2

我对ASP.NET MVC比较陌生,我发现自己有点像一个小门,或者更确切地说,在汤有点情况下。这是一个长度描述所以请耐心等待。如果这看起来有点长且无聊,我很抱歉:)。所以,这是我的问题:

这是我的模特。

public class SocialAccount
{
    public int SocialAccountID { get; set; }

    public int UserID { get; set; }

    public int SocialSiteID { get; set; }

    public string SocialAccountUsername { get; set; }

    public string SocialAccountUserID { get; set; }

    public string OAuthToken { get; set; }

    public string Captcha { get; set; }

    public string UserCaptchaValue { get; set; }
}

public class SocialSitePost
{
    public int PostID { get; set; }

    public string PostContent { get; set; }

    public string PostAttachments { get; set; }

    public List<SocialSite> SelectedSocialSites { get; set; }

    public List<SocialAccount> SocialAccount { get; set; }

}

public class SocialSite : Audit
{
   public int SocialSiteID { get; set; }
   public string SocialSiteName { get; set; }     
}

当用户成功通过身份验证后,我会在会话中存储一些用户详细信息并重定向到主页。这是代码:

//action method in some Controller
public Login()
{
     //Authenticate user

     //Get all social account related information
     SomeRepository someRepository = new SomeRepository();
     List<SocialAccount> socialAccountDetails = someRepository.SomeMethod(user.UserID);

     //Add social account related information to session
     HttpHelper.StoreInSession("UserDetails", socialAccountDetails);

     //redirect to HomePage
     return RedirectToAction("HomePage", "Account");
}

在HomePage操作方法中,我从会话中检索用户对象并检查已注册的社交帐户。我还创建了一个SocialSite的列表对象,以维护所有已注册社交网站的列表。然后我将其打包在ViewData并将其发送到视图。这是代码:

//action method in some other controller
public ActionResult HomePage()
{
     List<SocialSite> allSocialSites = null;
     List<SocialAccount> userSocialAccountDetails = HttpHelper.RetrieveFromSession("UserSocialSiteDetails") as List<SocialAccount>;

     if (userSocialAccountDetails != null && userSocialAccountDetails.Count != 0)
     {
          allSocialSites = new List<SocialSite>();
          bool hasFacebookAccount = userSocialAccountDetails.Exists(x => x.SocialSiteID == Convert.ToInt32(CommonConstants.SocialSite.Facebook));
          if (hasFacebookAccount)
          {
               allSocialSites.Add(new SocialSite() { SocialSiteID = 1, SocialSiteName = "Facebook" });
          }
          bool hasTwitterAccount = userSocialAccountDetails.Exists(x => x.SocialSiteID == Convert.ToInt32(CommonConstants.SocialSite.Twitter));
          if (hasTwitterAccount)
          {
               allSocialSites.Add(new SocialSite() { SocialSiteID = 2, SocialSiteName = "Twitter" });
          }
     }
     ViewData["SocialSites"] = allSocialSites;
     return View();
 }

我没有强类型视图。我需要做的是发布用户响应。所以我创建了一个POSTing表单。现在在此表单中,我想显示所有已注册社交帐户的复选框(ViewData会向我提供此信息)。因此,假设用户A只注册了一个Facebook帐户,那么只有1个代表Facebook的复选框应该是可见的。如果用户B注册了Facebook,Twitter和Instagram帐户,那么应该看到3个复选框,其中一个代表每个社交帐户。我想你明白了。这是我的代码:

@model SocialSitePost
@{
      using (Html.BeginForm("ProcesssRequest", "Account", FormMethod.Post))
      {
           <div class="divProcessRequest">
               <br />
               <div>
                   @Html.TextAreaFor(model => model.PostContent)
               </div>
               <div>
                   @foreach (var socialSite in ViewData["SocialSites"] as List<SocialSite>)
                   {
                        @Html.CheckBox("SocialSiteID", new { value = socialSite.SocialSiteID, @checked = true });
                        @Html.Label(socialSite.SocialSiteName)
                   }        //Tried this..And am able to display the checkbox

                   @*@for (int i = 0; i < Model.SelectedSocialSites.Count; i++)
                   {
                        @Html.CheckBoxFor("SocialSiteID", new { value = Model.SelectedSocialSites[i].SocialSiteID, @checked = true });
                   }*@        //Tried this too..I know this shouldn't work and rightly so, it doesn't work :)
               </div>
               <br />
               <div>
                   <input type="submit" id="btnPost" value="Post" />
               </div>
           </div>
      }
 }

够了!!! 现在我真正的问题

当用户选中任何复选框时,我想填充SelectedSocialSites对象的SocialSitePost属性。这是表单正在回发的对象的模型。我需要能够在POST方法中访问SelectedSocialSites属性。这就是我的POST方法:

[HttpPost]
public ActionResult ProcessRequest(SocialSitePost post)
{
     if (ModelState.IsValid)
     {
          List<SocialSite> allSocialSites = ViewData["SocialSites"] as List<SocialSite>;        //Can't get anything here
          int socialSiteNo = post.SelectedSocialSites.SocialSiteID;    //This is what I want to be able to do
          return View("HomePage");
     }
}

因为我对ASP.NET MVC比较陌生,所以我不确定这是否是正确的方法。我尝试了一些像EditorFor这样的东西,尝试在第一次渲染视图时发送SocialSitePost对象(我不想这样做,因为它没有任何逻辑意义)。

有人能告诉我如何根据用户提供的复选框选择获取POST方法中填充的SelectedSocialSites类的SocialSitePost属性吗?

此外,有人可以告诉我,如果我在这里做错了,因为到目前为止我还没有在SO上找到任何类似于这种情况的问题吗?

1 个答案:

答案 0 :(得分:2)

这里的主要问题是模型不完全适合需要显示的内容。也就是说,模型相对于视图的格式及其在后端的表示是不同的。因此,需要在此处使用ViewModel。这就解决了我的问题。

这些是我最终设计的ViewModels:

public class SocialSiteViewModel : SocialSite
{
    public bool IsSelected { get; set; }

    public string SocialSitePostID { get; set; }
}

public class SocialSitePostViewModel : SocialSitePost
{
    public List<SocialSiteViewModel> SocialSiteViewModel { get; set; }
}

然后我可以轻松地在视图上使用它们:

using (Html.BeginForm("ActionMethodName", "ControllerName", FormMethod.Post))
{

    @Html.CheckBoxFor(x => x.SocialSiteViewModel[i].IsSelected)
    @Html.HiddenFor(x => x.SocialSiteViewModel[i].SocialSiteID)
    @Html.HiddenFor(x => x.SocialSiteViewModel[i].SocialSiteName)
}