Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 5
×

Как обрабатывать собственные ошибки с сервиса

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

Я не знаю принято у вас тут задавать конкретные вопросы по программированию, но всё же решил написать, так как не имею представления, что написать в поисковом запросе, а на форумах сейчас мало людей.

Есть вебсервис, у него методы, которые возвращают строку с данными или с ошибкой, отличительная черта ошибки от данных — это в начале знак #.

Есть обычная функция (на клиенте) для авторизации.
В данном случаи не нужно возвращать какие то данные, но иногда бывает когда и нужно вернуть данные в вызывающий метод.

BaseRequest.IsError — только проверяет есть ли ошибка, как мне лучше и где показывать, что произошла ошибка.

есть несколько вариантов.
1. Просто в этой же функции и показывать ошибку.
2. Можно создать класс который, может хранить как ошибку так и данные и в зависимости от флага вызывающий метод будет уже работать с ним.
3. создать свои exceptions и обрабатывающий метода должен их обработать.

Как лучше я не знаю.

static public bool Login(string login, string password, RoleUser roleUser)
{
	string value = BaseRequest.Parse(strRequest, uri, AUTHORIZATION);
	int a = 0;
	if (BaseRequest.IsError(value))
	{
		Key = a;
		return true;
	}
	else
	{
		//error
		return false;
	}
}
👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Нотация bool Login — это гвнонотация. Если функция логическая — префикс у нее должен быть соответствующий: is, has и т.д. подходящее

Есть вебсервис, у него методы, которые возвращают строку с данными или с ошибкой, отличительная черта ошибки от данных — это в начале знак #

Нельзя так делать. Потому что ты себя ограничишь в том, что данные не смогут содержать в себе первый символ ’#’. А в некоторых файлах этот знак являет в себе символ закоментаренных строк. Признак ошибки, возвращаемой функцией, обычно служит отрицательное целочисленное значение ( = самый старший бит — в единице, далее накладывается маска и определяется побитово какие именно произошли ошибки)
Далее, если ты для доступа к вебсервису используешь WCF — почитай про FaultContract

Если ты не используешь WCF — на каждый успешный сеанс авторизации было бы хорошо возвращать некий уникальный авторизационный тоукен, типа гуида, даже в зашифрованном виде, который соотв. использовать как аргумент в методах вебсервиса, которые требуют авторизации (ну и конечно, сервер знает обо всех валидных тоукенах — чтобы не гонять туда сюда логин и пароль при вызове каждого метода, тем более, что этот тоукен можно хранить в кукисах — это для веб приложения). Или ничего не возвращать, если логин/пароль — невалидные Это, конечно, я рассматриваю самописную аутентификацию.

Можно и разрешить веб-ервису поддержку сессий (по-умолчанию она отключена), через
[System.Web.Services.WebMethod(EnableSession=true)]

При этом, логин / пароль можно хранить в сессии. Но с вариантом распределенного веб-сервиса (типа веб-фермы, когда кажды веб-сервис крутится на отдельном сервере,изолированно. соответственно, без костылей сессия на одном сервисе не пересекается с сессией другого — это может не подойти)

В ручную её не сложно написать.

с Login уже исправлено, теперь там другое возвращаемое значение.
С тоукеном так и делаю.
А с ошибками решил уже делать так: целочисленоеЗначение-данныеИлиОписаниеОшибки.

В общем вопрос уже решен.

Обычно — мухи отдельно, котлеты — отдельно:
2012
2010 year
-30 celsium degrees :)
Это — не сообщение об ошибке

ах да забыл.

100 — это код который говорит что ошибки нет =p

По такому принципу и отвечают, например, SMTP, POP3 сервера, особенно это видно, если с ними пообщаться через telnet. Теперь будешь городить свой сеансовый протокол, и его сопровождать.

городить — надеюсь хорошее слово.

не много изменений.

всегда возвращается формат кодОшибки-данныеИЛИописаниОшибки.

вот код смена пароля.
[code=csharp]
static public ResponceFromServer ChangePassword(string oldPassword, string newPassword)
{
string strRequest = BaseRequest.GenerationQuery(CHANGEPASSWORD, site,
new string[] { “key”, “oldPassword”, “newPassword” },

new object[] { Key, oldPassword, newPassword });

string value = BaseRequest.Parse(strRequest, uri, CHANGEPASSWORD);

return new ResponceFromServer(value);
}

[/code]

ResponceFromServer — класс который содержит если есть ошибку, код и данные.

правильно ли я делаю что отправляю в вызывающий метод этот объект а он там уже пусть решает сам что делать, или лучше ошибку обрабатывать и указывать прямо в ChangePassword?

Функции с такой сигнатурой на сервере вообще быть не может. Потому что не хватает уникальности — логина. Ведь у нескольких учетных записей может быть одинаковый пароль, верно?

КЕЙ уникальный, по нему сервис все поймет.

В смысле — у тебя все пароли уникальные?

Key и он берется из статической переменной, при авторизации кей записывается в неё и потом передается при каждом запросе.

Ну это у тебя — простейшая система, с одним предопределенным пользователем?

кей получает пользователь когда отдаёт серверу логин и пароль. после чего вся работа происходит по этому ключу.

Ключ — статический ведь? Ну залогинился другой пользователь — ключ первого на сервере похерился, у первого клиента теперь ключ — невалидный, или я не так понимаю?

Ключ храниться у каждого пользователя в своей копии программы.

А в базе храниться ключ\кто\когда пришел\когда ушел.

Ну то есть, при успешной авторизации, у тебя возвращается тоукен, далее любые методы, которые на сервере выполняются от имени пользователя, требуют передачи тоукена?

Ну это правильно.

Только вот ИМХО метод Login GetAuthorizationToken должен возвращать либо тоукен, либо string.Empty. При втором значении сообщать ’Wrong password or login name’. И без всякого объяснения, которое может быть у тебя закодировано. Чтоб брутфорсом не перебрали :) К эксепшну это тоже относится. А если в качестве логина используется емыл — то зачем кому-то знать, зареген такой-то емыл у тебя в базе, или нет. Это ведь авторизация — тут вообще нужно минимум сообщать

У меня новая сигнатура не много.

Он возвращает, класс в котором есть определение ошибка ли это, код ошибки, данные, описание ошибки.

static public ResponceFromServer Login(string login, string password, RoleUser roleUser) { string strRequest = BaseRequest.GenerationQuery(AUTHORIZATION, site, new string[] { "login", "password", "role" }, new object[] { login, password, (int)roleUser }); return BaseRequest.Parse(strRequest, uri, AUTHORIZATION);

как тут теги работают?=(

Есть просто стандартные шаблоны, все остальное (в т.ч. выдача избыточной информации, по какой причине авторизация отклонена) — от лукавого.

Ну не скажи.

Просто пишу сервер, который изначально пишется для использования другими разработчиками, по этому нужно вот такие вещи отдавать. А показывать или не показывать, пускай решают сами разработчики программы-клиента.

Ну так тем более, если ты пишешь API — нужно пользоваться принципом минимализма. А уже другие разработчики из твоих функций сами себе сделают нужную композицию. Например, я вижу ты заточился не только на проверку учетной записи, а еще, соответствует ли ей предлагаемая роль, и все при этом в одной функции? Фтопку однозначно. Потому что следуя золотому правилу «мухи — отдельно, котлеты — отдельно», хорошо было бы иметь 2 функции: одна — возвращает тоукен, вторая — проверку тоукена на участие в ролях. Если первая проверка прошла. Мне, как разработчику, было бы проще сделать композицию из твоих функций (сначала проверили данные учетной записи — логин пароль, получили тоукен, если не пустое значение — проверяем на членство в ролях. А как я пошлю сообщение пользователю — это уже моя головная боль, мне нужна от тебя только поведенческая логика). При этом, все твои функции в этом случае были бы уже функционально закончены. А если еще добавится, к примеру, еще один параметр для идентификации, кроме членства в ролях — то прийдется изменять твой метод Login. И прикручивать соответствующее сообщение.

ИМХО, тут уж тебе бы все отрефакторить и вынести в отдельные функции.

Это бы хорошо, но я специально это сделал, не хотел два запроса отправлять.

Да не вопрос — имея минималистические методы, там сам можешь делать полезные композиции. А если наращивается функциональность сторонним разработчиком — то он сделает композицию твоей полезной композиции со своей функцией. Тем более, чем минималистичнее твои функции — тем реальнее на них писать тесты. 2 запроса в смысле в базу? В данном контексте это допустимо.

два запроса от клиентской части до сервиса.

«два запроса хуже, чем один» — это понятие абстрактное, чтобы говорить, что это — плохо, нужно это выразить в каких-то единицах (хоть в килограммах). Навскидку могу сказать, что протокол HTTP (наверняка по нему на сервис будут ходить) соединение с сервисом все время не удерживает (в отличие от TCP) — после каждого вызова соотв. сокет закрывается. Но он — кешируется. Посему накладные расходы на то, чтобы достучаться к сервису составят 99.9999999999999% на первый вызов (потому что при первом вызове резольвится хост), и ноль и единицу в периоде на последующие (чтобы достать сокет из кэша). По TCP соединению — 100% и 0% соответственно, потому что TCP соединение связь удерживает постоянно. Итого — перформанс будет практически одинаковый. Даже, если будет хоть 100 запросов подряд (ну может, на несколько десятков милисекунд больше, при условии хорошего пинга между хостами). Зато ценой этих милисекунд у тебя будет нормальный набор веб-методов и расширяемый инструментарий для сторонних разработчиков.

Если используешь тоукен авторизации — передавай его как первый параметр, новый пароль — как второй параметр. В этом случае, только авторизованный пользователь сможетт сменить свой пароль. В противном случае — пароль можно поменять и без авторицации, а это не есть хорошо

Підписатись на коментарі