/// <summary> /// To hndle a request/response context. authorize, before/after filters /// </summary> /// <param name="rsc">the resource path</param> /// <param name="ac">ActionContext</param> /// <exception cref="AuthorizeException">Thrown when authorization is required and false is returned by checking</exception> /// <seealso cref="AuthorizeAttribute.Check"/> internal async Task HandleAsync(string rsc, ActionContext ac) { ac.Work = this; // authorize and filters if (!DoAuthorize(ac)) { throw AuthorizeEx; } Before?.Do(ac); if (BeforeAsync != null) { await BeforeAsync.DoAsync(ac); } int dot = rsc.LastIndexOf('.'); if (dot != -1) // file { // try in cache if (!Service.TryGiveFromCache(ac)) { DoFile(rsc, rsc.Substring(dot), ac); Service.Cache(ac); // try cache it } } else // action { string name = rsc; int subscpt = 0; int dash = rsc.LastIndexOf('-'); if (dash != -1) { name = rsc.Substring(0, dash); ac.Subscript = subscpt = rsc.Substring(dash + 1).ToInt(); } ActionInfo ai = string.IsNullOrEmpty(name) ? @default : GetAction(name); if (ai == null) { ac.Give(404); // not found return; } ac.Doer = ai; // action's authorization check if (!ai.DoAuthorize(ac)) { throw AuthorizeEx; } // action's before filtering ai.Before?.Do(ac); if (ai.BeforeAsync != null) { await ai.BeforeAsync.DoAsync(ac); } // try in cache if (!Service.TryGiveFromCache(ac)) { // method invocation if (ai.IsAsync) { await ai.DoAsync(ac, subscpt); // invoke action method } else { ai.Do(ac, subscpt); } Service.Cache(ac); // try cache it } // action's after filtering ai.After?.Do(ac); if (ai.AfterAsync != null) { await ai.AfterAsync.DoAsync(ac); } ac.Doer = null; } After?.Do(ac); if (AfterAsync != null) { await AfterAsync.DoAsync(ac); } ac.Work = null; }
internal async Task HandleAsync(string rsc, WebContext wc) { wc.Work = this; if (!DoAuthorize(wc, false)) { throw new WebException("authorize failed: " + Name) { Code = wc.Principal == null ? 401 : 403 }; } int slash = rsc.IndexOf('/'); if (slash == -1) // this work is the target work { if (Before != null) { if (Before.IsAsync && !await Before.DoAsync(wc) || !Before.IsAsync && Before.Do(wc)) { return; } } // // resolve the resource string name = rsc; int subscpt = 0; int dash = rsc.LastIndexOf('-'); if (dash != -1) { name = rsc.Substring(0, dash); wc.Subscript = subscpt = rsc.Substring(dash + 1).ToInt(); } var act = this[name]; if (act == null) { wc.Give(404, "action not found", true, 30); return; } wc.Action = act; if (!act.DoAuthorize(wc, false)) { throw new WebException("Do authorize failure: " + act.Name) { Code = wc.Principal == null ? 401 : 403 }; } // try in the cache first if (!Service.TryGiveFromCache(wc)) { // invoke action method if (act.IsAsync) { await act.DoAsync(wc, subscpt); } else { act.Do(wc, subscpt); } Service.TryAddForCache(wc); } wc.Action = null; if (After != null) { if (After.IsAsync && !await After.DoAsync(wc) || !After.IsAsync && After.Do(wc)) { return; } } } else // sub works { string key = rsc.Substring(0, slash); var wrk = GetSubWork(wc, key); if (wrk != null) // if child { // do necessary authentication before entering if (wc.Principal == null && !await wrk.DoAuthenticate(wc)) { return; } wc.AppendSeg(wrk, key); await wrk.HandleAsync(rsc.Substring(slash + 1), wc); } else if (varwork != null) // if variable-key subwork { // do necessary authentication before entering if (wc.Principal == null && !await varwork.DoAuthenticate(wc)) { return; } var prin = wc.Principal; object accessor; if (key.Length == 0) { if (prin == null) { throw AuthReq; } accessor = varwork.GetAccessor(prin, null); if (accessor == null) { throw AccessorReq; } } else { accessor = varwork.GetAccessor(prin, key); } // append the segment wc.AppendSeg(varwork, key, accessor); await varwork.HandleAsync(rsc.Substring(slash + 1), wc); } } }