2017-08-25 4 views
0

Lors du POST d'un ActionController, je reçois la grande référence d'objet '' non définie sur une instance d'un objet erreur.ASP.NET MVC - Objet nul dans ViewModel sur POST

Fondamentalement, j'ai besoin de l'ID de l'userRequest à enregistrer avec requestResponse. (Clé étrangère ici)

Voici le code.

ViewModel:

public class RequestResponseViewModel 
{ 
    public Models.Request userRequest { get; set; } 

    public Models.RequestResponse requestResponse { get; set; } 

} 

Vue: En debug ici il y a valeur model.userRequest.ID

@model UserRequests.ViewModels.RequestResponseViewModel 

    @{ 
    ViewBag.Title = "Create"; 
    } 

    <h2>Admin Response to Request</h2> 

    @using (Html.BeginForm()) 
    { 
    @Html.AntiForgeryToken() 

    <div class="form-horizontal"> 
     <hr /> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
     <div class="form-group"> 
      @Html.LabelFor(model => model.requestResponse.Response, 
    htmlAttributes: new { @class = "control-label col-md-1" }) 
      <div class="col-md-10"> 
       @Html.TextAreaFor(model => model.requestResponse.Response, new { 
    @class = "form-control", @rows = 5 }) 
       @Html.ValidationMessageFor(model => 
    model.requestResponse.Response, "", new { @class = "text-danger" }) 
      </div> 
     </div> 

     <div class="form-group"> 
       @Html.LabelFor(model => model.userRequest.ID, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-2"> 

       @Html.DisplayFor(model => model.userRequest.ID)    
       @Html.ValidationMessageFor(model => model.userRequest.ID, "", new { @class = "text-danger" }) 
      </div> 
      @Html.LabelFor(model => model.requestResponse.Author, htmlAttributes: new { @class = "control-label col-md-1" }) 
      <div class="col-md-3"> 
       @Html.EditorFor(model => model.requestResponse.Author, new { htmlAttributes = new { @class = "form-control" } }) 
       @Html.ValidationMessageFor(model => model.requestResponse.Author, "", new { @class = "text-danger" }) 
      </div> 
      @Html.LabelFor(model => model.requestResponse.CreateDate, htmlAttributes: new { @class = "control-label col-md-1" }) 
      <div class="col-md-3"> 
       <h5>@DateTime.Now</h5> 
       @Html.ValidationMessageFor(model => model.requestResponse.CreateDate, "", new { @class = "text-danger" }) 
      </div> 
     </div> 



     <div class="form-group"> 
      <div class="col-md-offset-1"> 
       <button type="reset" class="btn btn-default">Cancel</button> 
       <input type="submit" value="Create" class="btn btn-success" /> 
      </div> 
     </div> 
    </div> 

    <hr /> 
    <h3 class="text-success">Original Request</h3> 
    <div class="row"> 
     <div class="col-md-10"> 
      <h4>@Html.DisplayFor(model => model.userRequest.Title)</h4> 
     </div> 
    </div> 

    <div class="row"> 
     <div class="col-md-10"> 
      <h4>@Html.DisplayFor(model => model.userRequest.Description)</h4> 
     </div> 
    </div> 

    } 

    <div> 
     @Html.ActionLink("Back to Browse", "Browse","Change") 
    </div> 

Obtenez ActionResult:

public ActionResult Create(int id) 
    { 


     UserRequestContextDataContext db = new UserRequestContextDataContext(); 
     var request = (from m in db.Requests 
         where m.ID == id 
         select new Models.Request() 
         { 

          ID = m.ID, 
          Title = m.Title, 
          Description = m.Description, 
          BusinessUnit = m.BusinessUnit, 
          Author = m.Author, 
          ModuleName = m.MenuItem, 
          RequestStatus = 2, 
          SubmitDate = m.SubmitDate, 
          Type = m.Type, 
          UrgencyNum = m.UrgencyLevel 


         }).FirstOrDefault(); 

     var reqResponse = new Models.RequestResponse(); 


     var viewModel = new RequestResponseViewModel 
     { 
      userRequest = request, 
      requestResponse = reqResponse 

     }; 

     return View(viewModel); 
    } 

Le "viewModel" ici a tout ce dont j'ai besoin. Il a perdu quelque part entre les ActionResults ..

Enfin Post ActionResult:

[HttpPost] 
    public ActionResult Create(RequestResponseViewModel _requestResponseViewModel) 
    { 
     try 
     { 

      if (ModelState.IsValid) 
      { 
       using (UserRequestContextDataContext db = new UserRequestContextDataContext()) 
       { 

        RequestResponse reqRes = new RequestResponse(); 
        reqRes.Response = _requestResponseViewModel.requestResponse.Response.ToString(); 

        reqRes.RequestID = _requestResponseViewModel.userRequest.ID; 
        reqRes.Author = _requestResponseViewModel.requestResponse.Author.ToString(); 
        reqRes.CreateDate = DateTime.Now; 

        db.RequestResponses.InsertOnSubmit(reqRes); 
        db.SubmitChanges(); 
       } 
      } 

      return RedirectToAction("Browse","Change"); 
     } 
     catch (Exception ex) 
     { 

      return View("Error", new HandleErrorInfo(ex, "Change", "Create")); 
     } 
    } 

Utilisation du mode de débogage l'objet userRequest est NULL dans le paramètre du modèle de vue de la méthode POST, mais RequestResponse est FINE et peuplé comme devrait.

En cherchant sur ce point, il semblait que la plupart des problèmes de convention de nommage apparaissaient dans le modèle de vue, mais j'ai vérifié qu'il n'y avait pas de différences.

S'il y a un moyen de faire ce flux de travail plus clair s'il vous plaît mentionner ..

+0

Pouvez-vous poster la trace de la pile de l'erreur .. –

Répondre

1

@Html.DisplayFor ne crée pas un élément d'entrée HTML, mais une simple chaîne de (pour la plupart des types, certaines exceptions sont énumérées dans les documents: https://msdn.microsoft.com/en-us/library/ee407420(v=vs.118).aspx#Anchor_1). Ainsi, lorsque vous appuyez sur Envoyer, votre navigateur ne renvoie pas l'ID au serveur car il n'envoie que des données de formulaire (par exemple, des données provenant de l'entrée, du texte, de la sélection). En utilisant les outils de développement de votre navigateur (F12), vous pouvez examiner ce qui est réellement envoyé au serveur.

Vous pouvez ajouter un champ de saisie masqué à l'aide de @Html.HiddenFor(model => model.userRequest.ID) ou utiliser un modèle d'affichage personnalisé pour l'ID afin d'ajouter automatiquement un champ de saisie masqué. Vous pouvez également utiliser les attributs UIHint pour sélectionner automatiquement un modèle d'affichage. Les deux approches sont minutieusement documentées (par exemple http://www.codeguru.com/csharp/.net/net_asp/mvc/using-display-templates-and-editor-templates-in-asp.net-mvc.htm).

+0

Grande réponse, explication claire et des liens vers plus d'informations. Ajouter le HiddenFor a bien fonctionné. J'ai remarqué que je dois faire correspondre les champs hiddenFor() avec les champs de méthode GET que je récupère dans mon contrôleur ou que mon état de modèle n'est plus valide. –