2

ASP.NET MVC アーキテクチャに関する別の質問があります。ゆっくりとそこに到達し、ビットをつなぎ合わせていますが、解決しようとしているリンクがいくつかあります。私の現在のプロジェクト構造は以下のとおりです。私はそれに満足しています (ただし、建設的なコメントは素晴らしいでしょう)。私はまだ IoC/DI を使用していませんが、いつか使用する予定です。

私の質問は、AppName.Core.Services 名前空間にドメイン レベルのビジネス ロジックがありますが、これは素晴らしいことですが、アプリケーション キャッシュ内のものをチェックする HttpContext とやり取りする必要があるロジックがいくつかあります。本当に単純な例は、次のようなコードです。これ:

public int? GetCurrentClientId()
{
    int clientId = null;

    if (HttpContext.Current.Application["ClientId"] != null)
    {
        // Use value from application cache if one exists
        clientId = (int)HttpContext.Current.Application["ClientId"];
    }
    else
    {
        // Lookup using host name of site we are browsing
        string hostName = HttpContext.Current.Request.UserHostName.ToLower();
        UnitOfWork _unitOfWork = new UnitOfWork();
        Client client = _unitOfWork.ClientRepository.GetSingle(x => x.HostName.ToLower() == hostName || x.LocalHostNames.ToLower().Contains(hostName));
        if (client != null) clientId = client.Id;
    }
    return clientId;
}

AppName.Core.Services に HttpContext が認識されているため、すべてを貼り付けることはできないため、AppName.Core.Services に配置できる次のコードに分割していますが、よくわからないのはどこですか私のロジックは、必要に応じてこれを呼び出すために HttpContext などと対話します。コントローラーに入れたくありませんが、最適な場所、名前空間、規則などを考えています.

public int? GetClientIdFromHostName(string hostName)
{
    UnitOfWork _unitOfWork = new UnitOfWork();
    Client client = _unitOfWork.ClientRepository.GetSingle(x => x.HostName.ToLower() == hostName || x.LocalHostNames.ToLower().Contains(hostName));
    if (client != null) return client.Id;
    else return null;
}

この件に関する私の以前の調査と、ここで尋ねた以前の質問は、コントローラーからすべてのサービスにアクセスすることを示していました...しかし、サービスに HttpContext ベースのロジックを含めることができない場合、どこに行くことができますか??

ASP.NET MVC - サービス層、各コントローラー アクションの単一または多数のサービス?

プロジェクトの構造:

AppName.Core (for all my domain objects, DAL, domain services etc... independant and not aware of web specifics HttpContext etc)
> Data
> Data > DataContext.cs
> Data > UnitOfWork.cs
> Entities
> Entities > User.cs
> Entities > Client.cs etc etc
> Migrations
> Migrations > (all the EF code first migrations bits)
> Repository
> Repository > UserRepository.cs
> Repository > ClientRepository.cs
> Repository > GenericRepository.cs etc etc
> Services
> Services > ClientService.cs etc etc

AppName.Web (for all my compiled HttpContext aware code, ViewModels etc... references AppName.Core only)
> AutoMapper
> AutoMapper > Configuration.cs
> Controllers
> Controllers > UserController.cs
> Controllers > ClientController.cs etc etc
> Helpers
> Helpers > HtmlHelpers.cs
> ViewModels
> ViewModels > UserViewModel.cs
> ViewModels > ClientViewModel.cs etc etc

AppName (the ASP.NET MVC website project, no compiled code, Images/Css/JavaScripts etc... references AppName.Web only)
> Content
> Content > Images
> Content > Styles
> Scripts
> Views
4

2 に答える 2

1

次のようなヘルパーメソッドを作成できます。

public static TResult GetFromCacheOrSource<TResult>(string cacheIndex, Func<TResult> sourceMethod)
{
    TResult result = HttpContext.Current.Application[cacheIndex] as TResult;

    if (result == null)
    {
        // If there's no value in the cache go to the source
        result = sourceMethod();
    }     
    return result;
}

コントローラでは、次のようなことができます。

int? clientId = Helper.GetFromCacheOrSource<int?>("ClientId", () => clientService.GetClientIdFromHostname(hostname));
于 2012-06-18T23:15:03.607 に答える
1

サービスが MVC アプリ内からインスタンス化されている場合は、インターフェイス + ラッパー クラスを作成して、インスタンスをサービスに渡すことを検討できます。このようなもの:

interface IContext
{
    int? ClientID { get; }
}

class ContextWrapper : IContext
{
    private IHttpContext Context { get; set; }

    public ContextWrapper (IHttpContext context)
    {
        Context = context;
    }

    int? ClientID 
    {
        get 
        {
             return Context.Current.Application["ClientId"] != null
                    ? (int?)HttpContext.Current.Application["ClientId"]
                    : null;
        }
    }
}

class YourService
{
    public YourService(IContext context)
    {
        // store the reference and use in your methods as needed
    }
}

これにより、サービス クラスから System.Web に直接依存することがなくなります。また、IoC を使用し、コンストラクター インジェクションを使用して DI に簡単に接続できるため、これを単体テストするように適切に設定します。

于 2012-06-18T23:08:40.140 に答える