2

簡単だと思っていることをするのに助けが必要です。CodeFirst(CTP5)でASP.netMVC3を使用しています

会社と場所の2つのエンティティがあります。会社は多くの場所を作ることができます。クラスは次のとおりです(すべての不要な情報を取り除いた)

public class Company
{    
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual ICollection<Location> Locations { get; set; }
}

public class Location
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public virtual Company Company { get; set; }

}

現在、私のコントローラーでは、会社のコンテキスト内での場所の作成のみを許可しているため、会社IDは常に渡されます(ビューでは、読み取り専用フィールドに会社の名前を表示しますが、ユーザーは許可しませんそれを変更/編集します。

    public ActionResult Create(int companyId)
    {
        Company company = _session.Single<Company>(c => c.Id == companyId);
        Location newLocation = new Location {Company = company};
        return View(newLocation);
    } 

    [HttpPost]
    public ActionResult Create(Location location)
    {
        if (ModelState.IsValid)
        {
            _session.Add<Location>(location);
            _session.CommitChanges();                
            return RedirectToAction("Index");
        } else {
            return View(location);
        }
    }

これで、新しい場所を作成しようとすると、location.Company.Nameが指定されておらず、Companyの必須フィールドであるため、ModelState.IsValidは常にfalseになります。私はここで新しい会社を作成しようとはしていません。正しい会社を参照して場所を作成しようとしているだけです。ModelStateを検証するためだけに、Nameプロパティをビューに追加したくありません。どうすればこれを簡単に達成できますか?ビューとは異なるものを渡す必要がありますか?またはビューに?

4

2 に答える 2

2

コメントで説明しているように、この作業を行う小さな変更に遭遇しましたが、子IDパラメータを複製する必要がある理由がわからないため、それでも応急修理だと思いますが、それを見つけることができる最良/最も単純なものは将来的には簡単に更新できます。CodeFirstにあるもののすべて(またはほとんど)を知らないことを最初に認めます。

ロケーションクラスを次の場所から変更しました。

public class Location  
{      
    public int Id { get; set; }        

    [Required]      
    public string Name { get; set; }        

    [Required]      
    public virtual Company Company { get; set; }    
}

に:

public class Location  
{      
    public int Id { get; set; }        

    [Required]      
    public string Name { get; set; }        

    [Required]      
    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }    
}

私の知る限り、これはデータベーススキーマをまったく変更していませんが、(検証時に)Locationで必要なのは、CompanyIdフィールドにIDがあることだけであり、Companyプロパティはnullのままにすることができます。 (以前は、Companyクラスが必要だったため、適切なCompanyを検証しようとしていました)。

したがって、ロケーションを作成するときに、ビューがCompanyIdに戻す必要があるのはこれだけです。

誰かが欠点を見ますか?またはより良い方法?

于 2011-02-15T21:54:09.577 に答える
1

に会社名の隠しフィールドを簡単に追加できますform。そのデータは、期待どおりに取得され、POSTアクションに送信されます。

サーバー側で会社名をまったく使用しない場合は、会社IDが正しい限り(使用しているため)、この非表示フィールドにダミーテキストを入力できます。ただし、IDを使用して正しい会社名が必要な場合は、ダミーテキストではなく、実際の名前を非表示フィールドに入力する必要があります。

ともかく。これにより、会社名の非表示フィールドが追加されます

<%= Html.HiddenFor(m => m.Company.Name) %>

また、Companyプロパティを何にも設定していない場合は、次を使用することもできます。

<%= Html.Hidden("Company.Name", "Super duper company") %>

この値が実際の名前であるかダミーの名前であるかは、実際には重要ではありません。モデルはポストバック時に有効になります。

通常のポストバックまたはAjax?

Ajaxポストバックではなく、通常のポストバックを使用していると思います。Ajax oneを使用していて、jQueryを使用して呼び出している$.post()場合、または$.ajax()同様のものを使用している場合は、いつでも好きなオブジェクトを提供できます。JavaScriptコードに会社名の任意の値を入力できます。

JavaScriptに複雑なオブジェクトがあり、それらを強力な型パラメーターを使用してコントローラーアクションに送信したい場合(検証されるため)、この小さなjQueryプラグインを使用して、JSONオブジェクトをAspに正しく送信する準備をします。ネットMVCアクションにより、データは自動的に強力な型にデータバインドされて検証されます。JavaScriptも日付を記入しますか。:)

追加情報

エンティティは非常に進行中であり、必須フィールドを追加/削除している可能性があることを(コメントで)指摘したため、関連するすべてのビューも変更するのは非常に面倒な場合があります。

それでも、オブジェクトの状態に応じて変更可能なモデルやさまざまな検証シナリオに関して、生活を少し楽にするための方法がいくつかあります。

  1. アプリケーションモデルクラスに自動変換する機能も含む、作成プロセス用の個別のビューモデルを用意します。

    public class LocationCreate
    {
        public int Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public int CompanyId { get; set; }
    
        public Location ToModelInstance()
        {
            return new Location {
                Id = this.Id,
                Name = this.Name,
                Company = new Company {
                    Id = this.CompanyId,
                    Name = "Super duper company Ltd." // you can as well omit this line
                }
            };
        }
    }
    
  2. 継承を使用する:

    public class CompanyBase
    {
        public int Id { get; set; }
    }
    
    public class Company : CompanyBase
    {
        [Required]
        public string Name { get; set; }
    
        public virtual ICollection<Location> Locations { get; set; }
    }
    
    public class Location
    {
        public int Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public virtual CompanyBase Company { get; set; }
    
    }
    
于 2011-02-15T02:49:22.870 に答える