1

同じタイプで URI が異なる 2 つのハンドラーを登録する場合、ハンドラー選択アルゴリズムは、使用するハンドラーを決定するときに uri をチェックしていないようです。

以下のプログラムを実行すると、HandlerOne だけが (2 回) 呼び出されることがわかります。"/one" と "/two" のどちらを呼び出すかは関係ありません。後者は HandlerTwo によって処理されるはずです。

私は何か間違ったことをしていますか、それとも OpenRasta で修正されるものですか? (私は2.0.3.0を使用しています)

class Program
{
    static void Main(string[] args)
    {
        using (InMemoryHost host = new InMemoryHost(new Configuration()))
        {
            host.ProcessRequest(new InMemoryRequest
            {
                HttpMethod = "GET",
                Uri = new Uri("http://x/one")
            });
            host.ProcessRequest(new InMemoryRequest
            {
                HttpMethod = "GET",
                Uri = new Uri("http://x/two")
            });
        }
    }
}
class Configuration : IConfigurationSource
{
    public void Configure()
    {
        using (OpenRastaConfiguration.Manual)
        {
            ResourceSpace.Has.ResourcesOfType(typeof(object))
                .AtUri("/one").HandledBy(typeof(HandlerOne));
            ResourceSpace.Has.ResourcesOfType(typeof(object))
                .AtUri("/two").HandledBy(typeof(HandlerTwo));
        }
    }
}
class HandlerOne
{
    public object Get() { return "returned from HandlerOne.Get"; }
}
class HandlerTwo
{
    public object Get() { return "returned from HandlerTwo.Get"; }
}

更新http://trac.caffeine-it.com/openrasta/wiki/Doc/Handlers/MethodSelectionで 説明されているように、 UriNameHandlerMethodSelector を使用して同様のことを達成できると感じていますが、各ハンドラーに注釈を付ける必要がありますメソッドと AtUri().Named() も実行します。これは定型文のように見えますが、これは避けたいと思います。AtUri(X).HandledBy(Y) は X と Y の接続を明確にしていませんか?

4

3 に答える 3

5

ユージン、

同じリソース タイプでそのような複数の登録を行うべきではありません。また、おそらくResourcesOfType<object>URI に関連付ける必要もありません。これにより、OpenRasta で使用される解決アルゴリズムが完全に台無しになります。

2 つの異なるものをマッピングする場合は、2 つのリソース クラスを作成します。ハンドラーと URI はリソース クラスによってのみ関連付けられます。リソースの設計に失敗すると、OpenRasta は 2 つを一致させることができなくなります。これは仕様によるものです。

そのルートを維持したい場合、そしてそうすべきではないと私は本当に思いますが、名前を持つためにさまざまな URI を登録し、名前を使用して処理する必要があることを各メソッドに示唆することができHttpOperation(ForUriName=blah)ます この機能は、メソッドの自動解決をオプトアウトする必要がある非常にまれなシナリオでのみ利用できます。

最後に、OpenRasta は構成可能なフレームワークであるため、既存のクラスをハッキングする必要はありません。フレームワークにプラグインして、不要なコンポーネントをオーバーライドし、自分でコーディングしたものに置き換える必要があります。この場合、デフォルトが気に入らず、MVC スタイルの選択システムが必要な場合は、ハンドラーの選択を独自のモデルに置き換えるコントリビューターを簡単に作成できます。または、他のメソッドではなく特定のメソッドを選択する場合は、既存の操作セレクターを削除して、独自の操作セレクターに置き換える (または補完する) ことができます。そうすれば、公開された API に依存して OpenRasta を拡張し、コードが将来壊れることはありません。既存のコードをフォークしてハッキングした場合、その保証はできません。

于 2011-10-25T08:23:34.280 に答える
0

Seb が説明したように、同じリソース タイプで複数のハンドラーを登録すると、OpenRasta はハンドラーを 1 つの大きな連結されたクラスとして扱います。したがって、どの潜在的な GET (または他の HTTP 動詞) メソッドを実行するか (最も適切な表現方法) を推測し、最も適切であると判断します。これは、将来の開発者からは受け入れられず、解決する必要があります。

私はOpenRastaを使用して、同じリソースタイプを複数のハンドラーに登録できるようにする必要がありました。適切に正規化されたリレーショナル データベースからデータを取得する場合、複数の要求から同じタイプの応答を取得する必要があります。これは、(Linq で) 複数のクエリを作成して、1 対多の関係のいずれかの側からデータを取得するときに発生します。これはもちろん、データベースの構造全体にとって重要です。

Seb からのアドバイスを受け、彼の提案を正しく実装したことを願って、データベース モデル クラスを取得し、重複するリソース タイプが導入された可能性がある場合の各インスタンスのリソース名前空間で、そこから派生クラスを作成しました。

ResourceSpace.Has.ResourcesOfType<IList<Client>>()
                .AtUri("/clients").And
                .AtUri("/client/{clientid}").HandledBy<ClientsHandler>().AsJsonDataContract();

ResourceSpace.Has.ResourcesOfType<IList<AgencyClient>>()
                .AtUri("/agencyclients").And
                .AtUri("/agencyclients/{agencyid}").HandledBy<AgencyClientsHandler>().AsJsonDataContract();

Client は、AgencyClient を派生させた Model クラスです。

namespace ProductName.Resources
{
    public class AgencyClient: Client { }
}

Linq-SQL データ アクセス レイヤーから受け取った基本クラスを派生クラスにキャストする必要さえありません。とにかく、Linq キャスト メソッドはそのようなことを意図したものではありません。このコードはコンパイルされますが、間違っており、「LINQ to Entities は Entity Data Model プリミティブ型のキャストのみをサポートしています」という実行時例外を受け取ります。

Context.Set<Client>().Cast<AgencyClient>().ToList();  //will receive a runtime error

C# では SubClass への変換が簡単にできないため、(AgencyClient) のような従来型のキャストは機能しません。 基底クラスを派生クラスに変換する

AS 演算子を使用すると、再びコンパイルされて実行されますが、返されるリストに null 値が返されるため、意図したデータが取得されません。

Context.Set<Client>().ToList() as IEnumerable<AgencyClient>; //will compile and run but will return null

OpenRasta がハンドラーから ResourceType への異なる戻りクラスをどのように処理するかはまだわかりませんが、それを利用しましょう。おそらく、セブは詳しく説明できるでしょうか?

したがって、OpenRasta はこれらのクラスを個別に扱い、URI に対して適切なハンドラー メソッドが実行されます。

于 2012-12-13T15:25:17.267 に答える
-2

OpenRastaにパッチを当てて動作させました。これらは私が触れたファイルです:

OpenRasta/Configuration/MetaModel/Handlers/HandlerMetaModelHandler.cs
OpenRasta/Handlers/HandlerRepository.cs
OpenRasta/Handlers/IHandlerRepository.cs
OpenRasta/Pipeline/Contributors/HandlerResolverContributor.cs

主な変更点は、ハンドラー リポジトリがAddResourceHandlerへの初期化呼び出しで登録済みの URI を取得するようになったため、後でハンドラーの選択中に GetHandlerTypesFor が呼び出されたときに、URI もチェックできるようになったことですインターフェイスに関しては、これを変更しました:

public interface IHandlerRepository
{
    void AddResourceHandler(object resourceKey, IType handlerType);
    IEnumerable<IType> GetHandlerTypesFor(object resourceKey);

それに:

public interface IHandlerRepository
{
    void AddResourceHandler(object resourceKey, IList<UriModel> resourceUris, IType handlerType);
    IEnumerable<IType> GetHandlerTypesFor(object resourceKey, UriRegistration selectedResource);

簡潔にするために実装は省略します。

この変更は、OpenRasta が、現在のリクエストに関係のないハンドラー (メソッド シグネチャなど) をさらにチェックするために時間を無駄にしないことも意味します。

可能であれば、この問題について他の意見を求めたいと思います。多分私は何かを逃しただけです。

于 2011-10-19T06:35:46.050 に答える