Как получить доступ к IHttpRequest из моего собственного сериализатора в ServiceStack
У нас есть собственные сериализаторы для наших моделей, которые защищают конфиденциальные данные в зависимости от пути запроса. (Например, если запрос не начинается с "/admin").
До сих пор мы пытались зарегистрировать IHttpRequest с контейнером Funq в RequestFilter с ReuseScope.None или ReuseScope.Request, а на сериализаторах мы получаем IHttpRequest из контейнера.
Мы обнаружили, что если имеется несколько ожидающих запросов, контейнер вернет последний зарегистрированный IHttpRequest, который не всегда будет правильным объектом запроса.
Я знаю, что мы могли бы попытаться реализовать эту защиту конфиденциальных данных в наших моделях, применяя атрибуты фильтра, но это очень громоздко, поскольку наши объекты модели часто внедряются в другие объекты или коллекции.
Наличие сериализатора для этого является лучшим решением для нас, если мы не смогли получить правильный объект HttpRequest из сериализаторов.
Итак, что будет правильным способом сделать это? Или это плохая практика?
Вот несколько примеров кода:
Так что это частный метод, который мои сериализаторы используют для определения, сериализуются ли они в рамках маршрута "admin":
private bool IsAdminRoute() {
var path = container.Resolve<IHttpRequest> ().PathInfo;
var res = path.StartsWith ("/admin");
return res;
}
Вот использование этого:
public Question QuestionSerializer(Question question)
{
if (!IsAdminRoute())
{
// do stuff like nullyfying certain properties
}
return question;
}
На моей инициализации AppHost у меня есть:
void ConfigureSerializers(Funq.Container container)
{
Serializers = new CustomSerializers ();
// ...
JsConfig<Question>.OnSerializingFn = Serializers.QuestionSerializer;
// ...
}
public void HttpRequestFilter(IHttpRequest httpReq, IHttpResponse httpRes, object dto) {
Container.Register <IHttpRequest>(c => httpReq).ReusedWithin (Funq.ReuseScope.Request);
}
Примечание: я использую ServiceStack v3.
1 ответ
Мне удалось заставить его работать, зарегистрировав IHttpRequest следующим образом:
container.Register(c => HttpContext.Current.ToRequestContext ().Get<IHttpRequest>()).ReusedWithin(Funq.ReuseScope.None);
Теперь я всегда получаю объект IHttpRequest, который должен получить, когда пытаюсь разрешить их.
Кроме того, после более тщательного тестирования в моем приложении я смог обнаружить, что все, что зависело от регистрации в ReuseScope.Request, перепуталось, если параллелизм был достаточно высок.
Решение было довольно простым, теперь я полагаюсь на коллекцию HttpContext.Current.Items для хранения этих зависимостей, специфичных для запроса, и регистрации их в фильтре запросов следующим образом:
HttpContext.Current.Items ["Token"] = token;
container.Register<Token> (c => (Token)HttpContext.Current.Items["Token"]).ReusedWithin(Funq.ReuseScope.None);
Теперь это работает так, как и предполагалось каждый раз.