2012-02-23 16 views
3

私のコードでは基本クラスFooを持ち、すべてのオブジェクトはFooオブジェクトから継承しています。 それでは、私はApiControllersを使用しようとしました。このASP.NET Web APIコントローラは動的オブジェクトを処理できません。

public class Bar : Foo { 
    public string Heading { get;set; } 
} 

は、動的にメソッドを置くが、私はこれは私がApiController

で使用しているコードであり、このエラーに http://paste2.org/p/1914054

を得るように私はクラスを持っているとしましょう

public void Put(string id, dynamic model) { 
    //do stuff 
} 

通常のコントローラを使用している場合は、動的にデータを送信できます。 APIコントローラーを動的に動作させるか、独自のモデルバインダーを作成する必要がありますか?

MVC 3でも入力パラメータを動的にすることはできませんが、それは真実ではないと私はこの質問をしています。 MVC 3のThis controllerは、入力パラメータとして動的にうまく機能します。それはいくつかのように見ている

答えて

1

でもMVC 3で入力パラメータが が、私はそうは思わダイナミック

することはできないと思います。のは、提供された例を見てみましょう:

[HttpPost] 
[ValidateInput(false)] 
public virtual ActionResult Update(dynamic editorModel) { 

    if (!TryUpdateModel(_model, "CurrentModel")) { 
     var parentId = _model.Parent != null ? (string)_model.Parent.Id : null; 
     var viewModel = new EditViewModel 
     { 
      RootModel = _session.Query<IPageModel>() 
       .Where(model => model.Parent == null) 
       .SingleOrDefault(), 
      CurrentModel = _model, 
      ParentModel = parentId != null ? _session.Load<IPageModel>(parentId) : null, 
     }; 
     return View("edit", viewModel); 
    } 

    UpdateModel(_model); 

    _model.Metadata.Changed = DateTime.Now; 
    _model.Metadata.Published = _model.Metadata.IsPublished ? DateTime.Now : default(DateTime?); 
    _model.Metadata.ChangedBy = HttpContext.User.Identity.Name; 

    _repository.SaveChanges(); 
    _repository.Refresh(_model); 

    var page = _model as IPageModel; 

    if (page.Parent != null) { 
     _model = _repository.SingleOrDefault<IPageModel>(m => m.Id == page.Parent.Id); 
    } 

    return RedirectToAction("index", new { model = _model }); 
} 

は、あなたが場所を正確に、このコントローラのアクション内で使用されるこのeditorModel動的変数がどのように/私を指すことができますか?

さらに、このコントローラーアクションを単純化するために、引数として渡された動的変数を決して使用しないため、このコントローラーアクションは機能しません。私はより良いこのアクションはおおよそ(もちろん離れて、我々は問題を説明するためにここに興味を持っていませんすべてのインフラノイズを投げて)結合に関するモデルをやっていることを示すために、それを単純化しています

[HttpPost] 
public ActionResult Update(dynamic blablabla) 
{ 
    dynamic model = new MyViewModel(); 
    UpdateModel(model); 
    // at this stage the model will be correctly bound 

    return View(model); 
} 

このアクション内でTryUpdateModelをおよびUpdateModelメソッドは、コンストラクタに渡された_modelインスタンス変数で呼び出され、タイプはIPageModelです。 ASP.NET MVCは動的アクションの引数の型を(カスタムモデルバインダーなしで)知ることはできません。このコードを実行し、Updateアクションの中にブレークポイントを置き、editorModel変数のタイプを観察してください。単純にSystem.Objectになります。奇跡はありません。

これは私にとっては、これがASP.NET Web APIで同じように動作することは完全に正常です。

JSON配列を使用して
public string Post(dynamic value) 
    { 
     string s = ""; 
     foreach (dynamic item in value) 
     { 
      s = s + item.content + " "; 
     } 
     return s; 
    } 

+1

優秀な説明をいただき、ありがとうございました。抽象クラスのUserクラス、Userクラスを継承するAdministratorクラスを作成したい場合は、APIコントローラを使用してすべてのユーザーを保存したい場合はどうすればいいですか?それはカスタムモデルバインダーですか?もう一つの質問はUpdateModelです、これはapiコントローラには存在しませんので、既存のオブジェクトをどのように更新するのですか? – Marcus

+1

@Marcus、ASP.NET Web APIでは、このタスクを達成するためにカスタム 'MediaTypeFormatter'を書くことができます。シリアライザとしてJSON.NETを使用する[一例](http://code.msdn.microsoft.com/Using-JSONNET-with-ASPNET-b2423706)があります。 JSON.NETを使用すると、抽象クラスを直列化できる[custom JsonConverter'](http://stackoverflow.com/a/8031283/29407)を書くことができます。 –

+0

私の質問は、Userクラスを継承するタイプのUserの保存と更新に関するものです。この例ではhttp://pastebin.com/sRGW62ywを見てください。もちろん、入力パラメータはLastNameというプロパティを持たないのでUserにすることはできません。それで、入力パラメータは存在しないためバインドしません。これは私が知っている唯一のことは、入力パラメータがUserクラスを拡張しており、拡張クラスからすべてのデータを保存するためです。私がここでやろうとしていることを理解してくれることを願っています – Marcus

3

フム、私はASP.NETのWeb APIの方法でこれを行うことができた

POST http://localhost:6946/api/values HTTP/1.1 
User-Agent: Fiddler 
Host: localhost:6946 
Content-Length: 327 
Content-Type: application/json 
[{"content":"Hello","editing":false},{"content":"sfsdf","editing":false},{"content":"sadsdfdsf","editing":false},{"content":"dfsdf","editing":false},{"content":"dsfsd","editing":false},{"content":"sdfsdf","editing":false},{"content":"dsf","editing":false},{"content":"dfg","editing":false},{"content":"fsdfsd","editing":false}] 

そして、それは働いていた....

+0

それはASPのWeb APIでも私のために働いていました.Net MVC 4 –

0

http://www.binaryintellect.net/articles/589f6915-f4c0-4bf9-9f94-4d00bd445c16.aspx

このソリューションは完全に正常に動作します。

すべての入力コントロールが動的なHTMLフォームがありました。フォームデータをMVCコントローラに接続してから、もう一度Web API 2コントローラに接続するのは苦労しました。

お使いのサーバサイドのWeb APIメソッドは

public string Post(FormDataCollection form){ 
... } 

FormDataCollectionがSystem.Net.Http.Formatting名前空間に存在するようにする必要があります。

ウェブページ(jquery)から直接データをポーズしている場合は、上記のリンクソリューションがうまくいきます。

あなたがして、さらにウェブAPIメソッドに投稿されたMVCページ(C#コード)へのデータのWebページを掲示する場合、コードは次のようになります。

[HttpPost] 
    public async Task<string> MasterDraw(FormCollection body) 
    { 
     HttpClient client = new HttpClient(); 
     KeyValuePair<string, string>[] list = null; 
     string url = ConfigurationManager.AppSettings["BaseServiceUrl"] + "/api/MasterOperation/addrecord"; 

     if (body != null && body.HasKeys()) 
     { 
      list = new KeyValuePair<string, string>[body.AllKeys.Count()]; 
      for (int ctr = 0; ctr < body.Keys.Count; ctr++) 
      { 
       list[ctr] = new KeyValuePair<string, string>(body.Keys[ctr], body.GetValue(body.Keys[ctr]).AttemptedValue); 
      } 
     } 

     var content = new FormUrlEncodedContent(list); 

     HttpResponseMessage response = await client.PostAsync(url, content); 

     // Check that response was successful or throw exception 
     response.EnsureSuccessStatusCode(); 

     // Read response asynchronously as JToken and write out top facts for each country 
     string contentRes = response.Content.ReadAsStringAsync().Result; 

     return contentRes; 
    } 

ブラウザ側のコード:

$('#btn-save').on('click', function (event) { 
      var postUrl = "@Url.Action("masterdraw","masterrender")"; 

      var result = $.ajax({ 
       type: "POST", 
       data: $('#form').serialize(), 
       url: postUrl      
      }); 

      // insert your jquery .done and .error methods 

     }); 
関連する問題