2017-01-11 1 views
0

Ich habe eine Benutzerklasse mit einem Namen (eindeutig und erforderlich), einem Kennwort (erforderlich) und ein Profil (erforderlich). Die Profilklasse hat einen Namen, der eindeutig und auch erforderlich ist. Beide Klassen haben eine ID, die als Primärschlüssel fungiert, während die Datenbank zuerst mit Code generiert wird.Entität A hängt von Entität B ab, wie alle B-Informationen der Entität an POST gesendet werden. Methode der Entität A mit MVC-Code zuerst erstellen

ich die Schaffung neuer Benutzer in meiner Seite zulassen möchten, hier ist ein Code, dies zu tun:

-Controller

 // GET: Users/Create 
    public ActionResult Create() 
    { 
     populateViewBagWithProfilesAsSelectListItem(); 
     return View(); 
    } 

    private void populateViewBagWithProfilesAsSelectListItem() 
    { 
     IEnumerable<SelectListItem> profiles = db.Profiles.ToList(). 
      Select(x => new SelectListItem 
      { 
       Value = x.Id.ToString(), 
       Text = x.Name 
      }); 
     ViewBag.Profiles = profiles; 
    } 

    // POST: Users/Create 
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Create([Bind(Include = "Name,Password,Profile")] User user) 
    { 
     user.Profile = db.Profiles.Find(user.Profile.Id); 
     ModelState.Clear(); 
     TryValidateModel(user); 
     lock (UsersLocker) 
     { 
      if (ModelState.IsValid) 
      { 
       db.Users.Add(user); 
       db.SaveChanges(); 
       return RedirectToAction("Index"); 
      } 
     } 

     populateViewBagWithProfilesAsSelectListItem(); 
     return View(user); 
    } 

Ansicht erstellen

@model ProceduresRecord.Web.MVC.Models.User 

@{ 
    ViewBag.Title = "Crear"; 
} 

<h2>@ViewBag.Title</h2> 


@using (Html.BeginForm()) 

{ 
@Html.AntiForgeryToken() 

<div class="form-horizontal"> 
    <h4>Usuario</h4> 
    <hr /> 
    @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Profile, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.DropDownListFor(model => model.Profile.Id, (IEnumerable<SelectListItem>)ViewBag.Profiles, htmlAttributes: new { @class = "form-control" }) 
      @Html.ValidationMessageFor(model => model.Profile.Name, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="Crear" class="btn btn-default" /> 
     </div> 
    </div> 
</div> 
} 

<div> 
    @Html.ActionLink("Volver a la Lista", "Index") 
</div> 

Dies ergibt diese Seite:

Create user View

Wie man sehen kann ich die Profile aus der Datenbank zu füllen, zeige ich die Profile Namen für den Benutzer, sobald er ein nimmt und klickt auf erstellen, ein Id dieses Profils auf die POST-Methode gesendet wird, erstellen in Der Controller. Dann bemühe ich mich, das vollständige Profil aus der Datenbank mit der angegebenen ID zu erhalten, ich weise dem Benutzer das vollständige Profil zu und validiere den ModelState (so dass er sich in true ändert ... es ist falsch, weil das Profil keinen Namen hat bis jetzt). Es scheint alles zu funktionieren, aber ich frage mich ...

Gibt es keinen besseren Weg, dies zu tun? Ich meine, ich habe bereits die Profile aus der Datenbank, wenn die HTML-select bevölkern, wäre es nicht genial sein, um das komplette Profil auf die POST in einem Schuss und vermeiden Sie diesen Code zu senden:

 user.Profile = db.Profiles.Find(user.Profile.Id); 
     ModelState.Clear(); 
     TryValidateModel(user); 

Wenn Es gibt einen Weg, bitte sag es mir!

P.D: Ich versuche, MVC und Code First auf eigene Faust zu lernen, wird jeder Rat geschätzt.

+0

Verwenden Sie keine Datenmodelle in Ihrer Ansicht, insbesondere beim Bearbeiten. Erstellen Sie eine Ansicht Modell die Eigenschaften für 'Name', Passwort' und' SelectedProfile' - siehe Antwort von CodingYoshi (und keine der letzten 3 Zeilen des Codes in Ihrer Frage erforderlich ist) –

Antwort

1

Nicht sicher, was Ihre ModelState-Fehler sind. Aber Sie sollten wahrscheinlich eine Eigenschaft auf Ihrem User enitity ProfileId haben. Wenn nicht, sollten Sie wahrscheinlich einen hinzufügen. Dann können Sie Ihre Ansichten Profil Dropdown-Liste

@Html.DropDownListFor(model => model.ProfileId, (IEnumerable<SelectListItem>)ViewBag.Profiles, htmlAttributes: new { @class = "form-control" }) 

Dann Profile in Ihrem Bind(Include) der Aktion erstellen zu ProfileId und Ihre erstellen Aktion kann nur

// POST: Users/Create 
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598. 
[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "Name,Password,ProfileId")] User user) 
{ 
    lock (UsersLocker) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Users.Add(user); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
    } 

    populateViewBagWithProfilesAsSelectListItem(); 
    return View(user); 
} 

sein ändern sich ändern, wenn es nach mir ginge, würde ich Erstellen Sie eine neue Ansichtsmodellklasse UserViewModel mit den Eigenschaften Id, Name, Password und ProfileId, und übergeben Sie diese an die Ansicht.

+0

Danke, das war genau mein Fehler, den ich nur hatte eine Eigenschaft vom Typ Profil in meinem Benutzer, aber ProfilId des Typs int fehlte, ich wusste nicht, dass ich per Konvention beides haben sollte ... Ich habe mir nicht einmal vorstellen können, dass EF all diese Arbeit allein durch diese beiden Eigenschaften ausgeführt hat . Sehr geschätzt! – Loaderon

2

Wenn Sie Ihren Benutzer erstellen, benötigen Sie nicht die vollständige Profile, sondern nur die ID der Profile. Daher müssen Sie nur die Benutzerinformationen und die Profile ID eingeben. Wenn Sie einen neuen Benutzer erstellen und die Id-Eigenschaft Profile festlegen, wird EF dies für Sie herausfinden: Wenn das Profil mit diesem Schlüssel vorhanden ist, wird es es verwenden, andernfalls wird es sich beschweren, dass es ein Element mit dem bereitgestellten Fremdschlüssel nicht finden kann.

Auch würde ich ein Modell für die Ansicht erstellen, die wie folgt aussehen:

public class UserModel 
{ 
    public string UserName { get; set; } 
    public string Password { get; set; } 

    // This will be the selected profile id 
    public string SelectedProfileId { get; set; } 

    // fill this with all the profiles 
    public IEnumerable<SelectListItem> AvailableProfiles { get; set; } 
} 

Jeder SelectListItem kann wie folgt erstellt werden:

new SelectListItem 
    { 
     Value = ProfileId, // Whatever the property is 
     Text = ProfileName, // this will be displayed in dropdown 
    }); 

In Ihrem Controller eine Instanz, dass erstellen und Sende es zu deiner Ansicht.

aus Ihrer Sicht des Drop-down wie folgt erstellen:

@Html.DropDownListFor(m => m.SelectedProfileId, 
       new SelectList(m.AvailableProfiles)), 
       "Select Profile") 

dann in der Post die gewählten Profil-ID aus der SelectedProfileId Eigenschaft erhalten.

+0

Wenn Sie 'Selected = true' setzen, wird beim Binden an eine Modelleigenschaft nichts (wird von der' DropDownListFor() 'Methode ignoriert, da es der Wert von' SelectedProfileId' ist, der bestimmt, was ausgewählt ist) - ansonsten ist dies der richtige Ansatz –

+0

@stephenMuecke danke für den Tipp. Bearbeitete Antwort. – CodingYoshi

+0

Vielen Dank! Auch wenn die Antwort von JamieD77 besser zu meinem Mangel an Wissen passt, haben Sie sich als sehr hilfreich erwiesen! Ich wusste nicht, wie man View-Modelle verwendet, aber es stellte sich heraus, dass es sehr einfach und mächtig war. Vielen Dank! – Loaderon

Verwandte Themen