2013-01-18 3 views
2

Tout d'abord j'ai cherché ma question mais je n'ai rien trouvé qui m'a aidé à aller plus loin. J'essaye d'implémenter une vue qui me permet de placer des permissions pour l'utilisateur courant.ASP.NET MVC: passage d'un viewmodel complexe au contrôleur

Comme la structure de données i après l'utilisation de classe récursive où chaque PermissionTree-objet fait référence aux sous-autorisations (autorisations sont structurées hiérarchiquement dans ma demande):

public class PermissionTree 
{ 
     public Permission Node; //the permission object contains a field of type SqlHierarchyId if that is relevant 
     public bool HasPermission; 
     public IList<PermissionTree> Children; 
    //i cut out the constructors to keep it short ... 
} 

voici comment le contrôleur ressemble à:

//this is called to open the view 
public ActionResult Permissions() 
    { 
     //pass the root element which contains all permission elements as children (recursion) 
     PermissionTree permissionTree = PopulateTree();//the fully populated permission-tree 
     return View(permissionTree); 
    } 

//this is called when i submit the form 
    [HttpPost] 
    public ActionResult Permissions(PermissionTree model) 
    { 
     SetPermissions(model); 
     ViewData["PermissionsSaved"] = true; 

     return View(model);//return RedirectToAction("Index"); 
    } 

à l'aide d'une vue am fortement typé comme ceci:

@model PermissionTree 
//.... 
@using (Html.BeginForm("Permissions", "Permission", null, FormMethod.Post, new { @class = "stdform stdform2" })) 
{  
<input name="save" title="save2" class="k-button" type="submit" /> 

<div class="treeview"> 
//i am using the telerik kendoUI treeview 
    @(Html.Kendo().TreeView() 
      .Name("Permissions") 
      .Animation(true) 
      .ExpandAll(true) 
      .Checkboxes(checkboxes => checkboxes 
       .CheckChildren(true) 
      ) 
      .BindTo(Model, mapping => mapping 
       .For<PermissionTree>(binding => binding 
       .Children(c => c.Children) 
       .ItemDataBound((item, c) => { 
        item.Text = c.Node.PermissionName; 
        item.Checked = c.HasPermission; 
       }) 

       ) 
      ) 
    ) 

ok, donc quand je clique sur le bouton, je veux que mon viewmodel soit envoyé à l'action du contrôleur qui est décorée avec [HttpPost]. Mais quand je débogue l'application, le modèle reçu ne contient pas vraiment mes données (ce n'est pas nul cependant). Est-ce que quelqu'un sait comment je peux atteindre mon objectif et obtenir le modèle entier viewmodel?

meilleures salutations, r3try

+0

Avez-vous des champs de saisie dans votre vue? – ken2k

+0

non, je n'utilise qu'une arborescence avec des cases à cocher – r3try

+0

Essayez de voir ce qui se passe dans la liaison de modèle: http: // stackoverflow.com/questions/4651085/best-practices-for-débogage-asp-net-mvc-binding – ngm

Répondre

2

je pense qu'il est préférable d'utiliser un poste de JSON ici, alors il est facile de préparer l'objet dans le côté javascript. Je ne sais pas à quoi ressemble votre HTML ou les noms des éléments que vous pouvez facilement utiliser javascript/Jquery pour construire l'objet json côté client avec des noms similaires et une hiérarchie plus fine/dataTypes comme dans la classe PermissionTree. Et puis utiliser après Ajax pour poster JSON

var PermissionTree={Node:{},HasPermission:false,Children:{}} 
$.ajax({ data:PermissionTree 
          type: "POST", 
          url: 'YourController/Permissions', 
          contentType: "application/json; charset=utf-8", 
          dataType: "json", 
          success: function (result) { 
       } 
); 

L'important est que vous devez trouver une meilleure façon d'aller throuth la vue des arbres et construire l'objet en javascript.

+0

Je pense que je ne comprends pas complètement cela ... vous voulez dire quand je clique sur le bouton soumettre je devrais utiliser javascript pour créer l'objet sérialisé manuellement et puis poster les données à mon contrôleur en utilisant ajax? Je ne comprends vraiment pas pourquoi il y a des vues fortement typées dans mvc quand vous ne pouvez même pas renvoyer ce viewmodel au contrôleur. n'est-ce pas le point de vue pour modifier le modèle? .. \ * soupir \ * frustration de côté - merci pour votre réponse! ;) – r3try

+1

Le problème est avec la collection de modèles que vous avez. Pour publier une vue avec types forts et pour peupler le modèle, vous devez utiliser une convention de dénomination appropriée dans la vue. Je veux dire dans le HTML vos entrées devraient avoir des noms comme 'Children [0] .Chilren [1] .Permission' comme exemple. –

+0

Si vous n'avez pas le meilleur moyen de remplir un objet JSON et de le transmettre en utilisant Ajax. –

0

que je ne peux pas obtenir que pour travailler je tentais une approche légèrement différente:

exemple pour ajouter un nœud: - appuyez sur le bouton ajouter -> execute appel ajax -> ajouter le nœud dans NHibernate -> appeler la vue à nouveau avec les nouvelles données (le nouveau nœud inclus)

contrôleur-action qui est appelé par la demande ajax:

[Authorize] 
    [HttpPost] 
    public ActionResult AddPermission(string parentPermissionName, string permissionName) 
    { 
     var pd = ServiceContext.PermissionService.permissionDao; 
     Permission parentPermission = pd.GetPermissionByName(parentPermissionName); 
     if (parentPermission == null) { 
      parentPermission = pd.GetRoot(); 
     } 

     if (parentPermission != null && !string.IsNullOrEmpty(permissionName) && !pd.PermissionExists(permissionName))//only add with a name 
     { 
      pd.AddPermission(parentPermission, permissionName); 
     } 
     //refresh data 
     PermissionTree permissionTree = LoadTreeSQLHierarchy(null, false);//start at root 
     return View("Permissions", permissionTree); 
    } 

Ajax demande dans la vue:

function addNode() { 
    //... get the data here 
    var addData = { parentPermissionName: selectedNodeName, permissionName: newNodeName }; 

    $.ajax(
     { 
      data: addData, 
      type: "POST", 
      url: '@Url.Action("AddPermission", "Permission")', 
      dataType: "json", 
      success: function (result) { 
       //$('.centercontent').html(response);//load to main div (?) 
       return false; 
      }, 
      error: function (xhr, ajaxOptions, thrownError) { 
       alert(xhr.status + ":" + thrownError); 
       return false; 
      } 
     } 
    ); 
    return false; 
} 

Mais quand j'exécute ceci j'obtiens une erreur indiquant que json.parse frappe un caractère invalide (j'obtiens cette erreur à l'alerte dans la fonction d'erreur d'ajax). A en juger par ce message, je dirais que le problème est que je retourne html mais l'appel ajax attend json ou alors ... Mais quelle est la bonne façon de simplement recharger ma vue avec les nouvelles données? Puis-je en quelque sorte dire à l'appel ajax de ne pas revenir du tout et juste d'exécuter la méthode de contrôleur appelée?

Questions connexes