Persisting data back to ViewModel with a dynamic .

2019-08-27 11:36发布

问题:

I have a view that is created dynamically with objects from my database. How can I take the values from my View and pass them to my view model if it is created dynamically? I know this question is vague but hopefully looking through my code will help you help me.

View

  <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) {%>
<h1>Survey Says...</h1>
<ol>       
<li>
    Name: <input type="text" disabled="true" name="name" value="<%= Model.Name %>"/> 
</li>                                                  

<li>
    Email: <input type="text" disabled="true" name="email" value="<%= Model.Email %>"/>
</li>

<%foreach(SurveyQuestions s in Model.myQuestions)
  { %>   

    <li>    <%= s.QuestionText %>    <br />
    <%
    foreach(SurveyQuestionAnswers q in s.QuestionAnswers)
    {

    %>
        <input type="radio" name="rbGroup<%= q.Id%>"/> <%= q.DisplayText %><br/>

        <% 
     if(q.IsEditable)
     {
         %>
            <input type="text" id="txtOther<%= q.Id %>"/>
         <%
     }
    }
      %>           


    </li>

 <% } 

  %>      
           <li>
    <input type="submit" value="Save" id="save-button" />
</li>

</ol>
<% } %>

SurveyQuestion class

public class SurveyQuestions
{
    public string QuestionText { get; set; }
    public List<SurveyQuestionAnswers> QuestionAnswers { get; set; }
    public int Id { get; set; }
}

SurveyQuestionAnswers class

 public class SurveyQuestionAnswers
{
    public int Id { get; set; }
    public string DisplayText { get; set; }
    public bool IsEditable { get; set; }
}

My sloppy ViewModel

          public class GfcPreInterventionSurveyViewModel
{
    static SurveyService myService = new SurveyService(new SurveyRepository());

    [DisplayName("Name")]
    [Required(ErrorMessage = "Name is required.")]
    public string Name { get; set; }

    [DisplayName("Work Email")]
    [Email(ErrorMessage = "The email you entered is not valid.")]
    public string Email { get; set; }

    [DisplayName("Gender")]
    [Required(ErrorMessage = "Gender is required.")]
    public string Gender { get; set; }


    [DisplayName("Country")]
    [Required(ErrorMessage = "Country is required.")]
    public string Country { get; set; }

    [DisplayName("Business")]
    [Required(ErrorMessage = "Please select a business unit.")]
    public string BusinessUnit { get; set; }

    public SelectList GenderList;
    public SelectList BusinessList;
    public SelectList CountryList;
    public SelectList RoutineList;
    public SelectList ReasonList;
    public SelectList ActivityList;
    public SelectList HealthList;
    public SelectList EnergyList;

    public SelectListItem GenderItem;
    public SelectListItem BusinessItem;
    public SelectListItem CountryItem;
    public SelectListItem RoutineItem;
    public SelectListItem ReasonItem;
    public SelectListItem ActivityItem;
    public SelectListItem HealthItem;
    public SelectListItem EnergyItem;


    public Boolean ToGetFit { get; set; }
    public Boolean ToChallengeMyself { get; set; }
    public Boolean ToIncrEnergy { get; set; } 
    public Boolean ToBuildMorale { get; set; }
    public Boolean ToBeHealthier { get; set; }
    public Boolean ChallengeOther { get; set; }

    public string OtherString { get; set; }    

    [DisplayName("Exercise Routine")]
    [Required(ErrorMessage = "Which option describes your exercise routine.")]
    public string Routine { get; set; }


    [DisplayName("Physical Activity")]
    [Required(ErrorMessage = "Which option describes your physical activity.")]
    public string Activity { get; set; }


    [DisplayName("Overall Health")]
    [Required(ErrorMessage = "Which option describes your overall health.")]
    public string Health { get; set; }

    [DisplayName("Energy")]
    [Required(ErrorMessage = "Which option best describes your energy.")]
    public string Energy{ get; set; }

    public int ReasonsForChallenge { get; set; }



    public List<SurveyQuestions> myQuestions = new List<SurveyQuestions>();
    //public List<SurveyQuestionAnswers> myAnswers;


    public void build(int id)
    {
        var myService = new SurveyService(new SurveyRepository());

        myQuestions = myService.GetSurveyQuestions(id);

            }

my getSurveyQuestions method returns a List of SurveyQuestions objects.

currently, in my controller, when save is hit, the post method is called. this is where i want to update my database with the values in the viewmodel, but because my page is so dynamic, i am having trouble accessing the user's input.

My Controller:

public class SurveyController : WidgetControllerBase
{
    #region Private Members
    private readonly ISurveyRepository _surveyRepository;
    #endregion

    #region Constructors

    public SurveyController(ISurveyRepository surveyRepository)
    {
        if (surveyRepository == null)
        {
            throw new ArgumentNullException("surveyRepository");
        }
        _surveyRepository = surveyRepository;
    }

    #endregion

    // GET: /Survey/GfcPreIntervention
    public ActionResult GfcPreInterventionSurvey()
    {

        var surveyService = new SurveyService();
        var vm = new GfcPreInterventionSurveyViewModel();

        vm.build(AppUserInstance.Id);

        //paymentService.SetDVDShipped(payment.PaymentId);
        return View(vm);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult GfcPreInterventionSurvey(GfcPreInterventionSurveyViewModel viewModel)       
    {
        return View(viewModel);                     
    }
}

回答1:

Since your page is highly dynamic, maybe you would be better off writing a custom model binder. Though the term sounds intimidating it’s not actually that complicated.

You would simply create a class which would implement IModelBinder. Within this class, you would have access to the form collection and can populate any complex object(s) with it

Following are some examples worth looking at

http://dotnetslackers.com/articles/aspnet/Understanding-ASP-NET-MVC-Model-Binding.aspx

http://ivanz.com/2010/11/03/custom-model-binding-using-imodelbinder-in-asp-net-mvc-two-gotchas/

And as you have figured out, using helper methods (preferably with Razor) will clean up the UI code