Я относительно новичок в 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();
}
У меня нет строго типизированного представления. Что мне нужно сделать, это опубликовать ответ пользователя. Поэтому я создаю форму для POST. Теперь в этой форме я хочу показать флажок для всех зарегистрированных социальных учетных записей (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
. Это модель, объект которой возвращает форма. Мне нужно иметь доступ к свойству SelectedSocialSites
в методе POST. Так мой метод 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
при первом просмотре представления (я не хочу этого делать, поскольку он не имеет никакого логического смысла).
Может кто - нибудь сказать мне, как я могу получить SelectedSocialSites
свойство SocialSitePost
класса заселенной в методе POST, основанный на флажке выбора, сделанного пользователем?
Кроме того, может кто-нибудь сказать мне, если я делаю что-то неправильно здесь, так как я не нашел здесь каких-либо вопросов о SO, которые кажутся похожими на такую ситуацию?
Основная проблема здесь в том, что модель не полностью подходит для того, что нужно отображать. То есть формат модели в отношении представления и его представления на бэкэнд отличается. Следовательно, здесь нужно использовать 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)
}