0

私はMVCasp.net4とjqueryを使用しています。これが私の問題です:私は次のモデルを持っています:

public class PledgeModel
{
    public string name { get; set; }
    public IList<AbstractAsset> Assets { get; set; }
}

1つは、そのプロパティがオブジェクトのリストであり、それぞれが抽象クラスを継承している場合です。

public abstract  class AbstractAsset
{
    public string commetns { get; set; }
}


public class RealEstateAsset:AbstractAsset
{
    public int CityId { get; set; }
}
public class TransportationAsset : AbstractAsset
{
    public string LicenseNumber { get; set; }
}

}

これが私の「Get」アクションコードです。

       //init new Pledge  
        PledgeModel pledge=new PledgeModel();
        pledge.name = "Moses";
        pledge.Assets=new List<AbstractAsset>();

        RealEstateAsset realEstateAsset = new RealEstateAsset();
        TransportationAsset transportationAsset=new TransportationAsset();

        realEstateAsset.CityId = 1;
        transportationAsset.LicenseNumber = "7654321";

        pledge.Assets.Add(realEstateAsset);
        pledge.Assets.Add(transportationAsset);


        ViewBag.Pledge = pledge;

ビューのJsonで誓約モデルを取得すると、次のjsonが表示されます。

{"name": "Moses"、 "Assets":[{"CityId":1、 "commetns":null}、{"LicenseNumber": "7654321"、 "commetns":null}]};

モデル全体とそのアセットリストをajaxコールバックで送信しようとしている場合:

                              var ajaxOptions = {
                                type: 'post',
                                url: 'Home/TryInsertPledge',
                                contentType: "application/json, charset=utf-8;",
                                dataType:'json',
                                data:JSON.stringify({pledge:pledge}),
                                success: function(data) {
                                    alert('success');
                                },
                                error: function() {
                                    alert('error');
                                }
                              };
                              $.ajax(ajaxOptions);

「投稿」アクション:

   [HttpPost]
   public JsonResult TryInsertPledge(PledgeModel pledge)
   {


       return Json(new {sucess = "success"});
   }

何らかの理由でエラーが発生しました(Chrome開発者ツールでリクエストの赤いエラーをクリックした場合)'抽象クラスを作成できません'

しかし、資産リストが空の場合-私は私の誓約を正しく取得しました

助けてください

ありがとう

4

2 に答える 2

0

あなたの Ajax 呼び出しでは、誓約は何から生成されていますか? フォームの場合、各抽象アセットのすべてのプロパティが何らかの形でフォームに含まれていることを確認する必要があります。これらをユーザーが編集できる入力フィールドにしたくない場合は、入力フィールドのタイプを非表示に設定します。

それが役立つことを願っています!

于 2013-01-09T11:58:13.143 に答える
0

http://maciejlis.com/asp-mvc-3-model-binder-with-abstract-class-support/のおかげで 、問題の解決策が得られました。

customBinder を追加しました (maciejlis ブログから完全にコピーされました) このカスタム バインダーは、タイプ プロパティに従ってアセット オブジェクトをマッピングします (アセット クラス名とまったく同じである必要があります)。

    public class EnhancedDefaultModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            Type type = modelType;
            if (modelType.IsGenericType)
            {
                Type genericTypeDefinition = modelType.GetGenericTypeDefinition();
                if (genericTypeDefinition == typeof(IDictionary<,>))
                {
                    type = typeof(Dictionary<,>).MakeGenericType(modelType.GetGenericArguments());
                }
                else if (((genericTypeDefinition == typeof(IEnumerable<>)) || (genericTypeDefinition == typeof(ICollection<>))) || (genericTypeDefinition == typeof(IList<>)))
                {
                    type = typeof(List<>).MakeGenericType(modelType.GetGenericArguments());
                }
                return Activator.CreateInstance(type);
            }
            else if (modelType.IsAbstract)
            {
                string concreteTypeName = bindingContext.ModelName + ".Type";
                var concreteTypeResult = bindingContext.ValueProvider.GetValue(concreteTypeName);

                if (concreteTypeResult == null)
                    throw new Exception("Concrete type for abstract class not specified");

                type = Assembly.GetExecutingAssembly().GetTypes().SingleOrDefault(t => t.IsSubclassOf(modelType) && t.Name == concreteTypeResult.AttemptedValue);

                if (type == null)
                    throw new Exception(String.Format("Concrete model type {0} not found", concreteTypeResult.AttemptedValue));

                var instance = Activator.CreateInstance(type);
                bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, type);
                return instance;
            }
            else
            {
                return Activator.CreateInstance(modelType);
            }
        }
    }

あとは、各アセット オブジェクトに「Type」プロパティを追加するだけです。

            $(pledge.Assets).each(function () {

                this.Type = (typeof this.CityId !== 'undefined') ? 'RealEstateAsset' : 'TransportationAsset';

            });





            var ajaxOptions = {
                type: 'post',
                url: 'Home/TryInsertPledge',
                dataType: 'json',
                contentType: "application/json, charset=utf-8;",
                data: JSON.stringify({ pledge: pledge }),
                success: function (data) {

                       alert('success');
                },
                error: function (xhr) {
                    alert(xhr.respnseText);
                }
            };
            $.ajax(ajaxOptions);

そして、資産はサーバーに正しく到達しました...ありがとう、maciejlis

于 2013-01-13T16:46:26.750 に答える