customer use http://aaa.com/uploads/bb/index.html to request my ASP.NET MVC site. I want to make sure the customer has enough permission to access the site, so I need catch the request and deal with it. I'm using IHttpModule to do that.
public class myHttpModule : IHttpModule {
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
Uri url = application.Context.Request.Url;
string path = url.AbsoluteUri;
}
}
the question is when second time use the same url to request the website, the HttpModule can't catch the request.
got the answer!It's about the http cache.
I write code as below and the problem was killed:
public class myHttpModule : IHttpModule {
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
Uri url = application.Context.Request.Url;
string path = url.AbsoluteUri;
**app.Response.Cache.SetCacheability(HttpCacheability.NoCache);**
}
}
Related
I'm currently programming a Discord RPC client, which shows a preview of the Presence.
I found out, that with "https://discordapp.com/api/oauth2/applications/[appid]/assets" you get the asset id from the application and with it the image using "https://cdn.discordapp.com/app-assets/[appid]/[assetid].png". But how do i get the application name with the client id?
I have this class, which sets AppName in customStatus class
class getAppName
{
static DiscordRpcClient client;
public getAppName(string AppId)
{
client = new DiscordRpcClient(AppId);
client.Initialize();
client.OnReady += OnClientReady;
client.OnPresenceUpdate += Client_OnPresenceUpdate;
}
private void Client_OnPresenceUpdate(object sender, PresenceMessage args)
{
customStatus.AppName = (args.Name);
client.ClearPresence();
client.Dispose();
}
private void OnClientReady(object sender, ReadyMessage args)
{
client.SetPresence(new RichPresence { });
}
}
And in customStatus class:
public static string AppName { get; set; }
And:
new getAppName("AppId");
var oldName = AppName;
//this is to wait until the new appname is set
while (oldName == AppName) {}
string newAppname = AppName;
Hope it works for you!
Right now, I am in the process of "optimizing" my app. I am still a beginner, so what I am doing is basically moving methods from my MainActivity.class to their separate class. I believe it's called Encapsulation (Please correct me if I'm wrong).
My application needs to :
Get a YouTube Playlist Link from the YouTube App (with an Intent, android.intent.action.SEND).
Use the link to fetch data from the Google Servers with the YouTubeApi and Volley.
Read the data received and add it to an arrayList<String>.
What my YouTubeUsage.java class is supposed to do, is fetch data with the YouTubeApi and Volley then store the data using SharedPreferences. Once the data is saved, the data is being read in my ConvertActivity.class (It's an activity specifically created for android.intent.action.SEND) with my method getVideoIds() before setting an adapter for my listView in my createRecyclerView() method.
YouTubeUsage.java
public class YoutubeUsage {
private Boolean results = false;
private String mResponse;
private ArrayList<String> videoIds = new ArrayList<>();
String Url;
public String getUrl(String signal) {
String playlistId = signal.substring(signal.indexOf("=") + 1);
this.Url = "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails%2C%20snippet%2C%20id&playlistId=" +
playlistId + "&maxResults=25&key=" + "API_KEY";
return this.Url;
}
public void fetch(String Url, final Context context){
RequestQueue queue = Volley.newRequestQueue(context);
StringRequest request = new StringRequest(Request.Method.GET, Url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
sharedPreferences(response, context);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VolleyError", Objects.requireNonNull(error.getMessage()));
}
});
queue.add(request);
}
private void sharedPreferences(String response, Context context){
SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = m.edit();
if (m.contains("serverResponse")){
if (!m.getString("serverResponse", "").equals(response)){
editor.remove("serverResponse");
editor.apply();
updateSharedPreferences(response, context);
}
} else{
updateSharedPreferences(response, context);
}
}
private void updateSharedPreferences(String mResponse, Context mContext){
SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = m.edit();
editor.putString("serverResponse", mResponse);
editor.apply();
}
}
ConvertActivity.java
public class ConvertActivity extends AppCompatActivity {
YoutubeUsage youtubeUsage = new YoutubeUsage();
ArrayList<String> videoIDs = new ArrayList<>();
String Url = "";
ListView listView;
MyCustomAdapter myCustomAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_convert);
listView = findViewById(R.id.listview_convert);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
Url = youtubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
}
//I would like to avoid the try/catch below
try {
videoIDs = getVideoIDs(Url, this);
createRecyclerView(videoIDs);
Log.i("ResponseVideoIDs", String.valueOf(videoIDs.size()));
} catch (JSONException e) {
e.printStackTrace();
}
}
private ArrayList<String> getVideoIDs(String Url, Context context) throws JSONException {
ArrayList<String> rawVideoIDs = new ArrayList<>();
youtubeUsage.fetch(Url, context);
SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(context);
String serverResponse = m.getString("serverResponse", "");
JSONObject jsonObject = new JSONObject(serverResponse);
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i<jsonArray.length(); i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject jsonVideoId = jsonObject1.getJSONObject("contentDetails");
rawVideoIDs.add(jsonVideoId.getString("videoId"));
}
return rawVideoIDs;
}
private void createRecyclerView(ArrayList<String> videoIDs){
myCustomAdapter = new MyCustomAdapter(this, videoIDs);
listView.setAdapter(myCustomAdapter);
myCustomAdapter.notifyDataSetChanged();
}
}
Everything works fine, however, my sharedPreferences never gets updated. Which means, if I share a YouTube playlist from the YouTube App to my app with 3 items in it, it will work fine. The Listview will show 3 items with their corresponding IDs as it should. But, if I share a YouTube playlist again, my app will still hold on to the data of the previous playlist I shared (even if I close it), showing the item number and the IDs of the previous link. If i continue to share the same playlist over and over, it will eventually show the correct number of items and the correct IDs.
I could totally put all my methods from the YouTubeUsage.java in my ConvertActivity.class preventing me from using SharedPreferences to transfer data between the two java classes. However, JSON throws an exception. That means I have to encapsulate my code with try/catch. I would like to avoid those since I need to do a lot of operations on the data just received by Volley (check a class size, look for certains strings). I find that doing this in these try/catch don't work like I want. (i.e. outside the try/catch, the values remains the same even if I updated them in the try/catch).
I want to know two things.
How can I correct this problem?
Is this the most efficient way to do this (optimization)? (I though of maybe
converting the VolleyResponse to a string with Gson then store the String file, but I don't know if that's the best way to do it since it's supposed to be
provisional data. It feels like just more of the same).
Thank You!
There is an issue with making assumptions about order of events. Volley will handle requests asynchronously, so it is advisable to implement the observer pattern here.
Create a new Java file that just contains:
interface MyNetworkResponse {
void goodResponse(String responseString);
}
Then make sure ConvertActivity implements MyNetworkResponse and create method:
void goodResponse(String responseString) {
// handle a positive response here, i.e. extract the JSON and send to your RecyclerView.
}
within your Activity.
In your YoutubeUsage constructor, pass in the Activity context (YoutubeUsage) and then store this in a YoutubeUsage instance variable called ctx.
In onCreate, create an instance of YoutubeUsage and pass in this.
In onResponse just call ctx.goodResponse(response).
Amend the following block to:
if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
Url = youtubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
youtubeUsage.fetch(Url);
}
Delete the try/catch from onCreate.
And no need to use SharedPreferences at all.
UPDATE
Try this code:
MyNetworkResponse.java
interface MyNetworkResponse {
void goodResponse(String responseString);
void badResponse(VolleyError error);
}
YoutubeUsage.java
class YoutubeUsage {
private RequestQueue queue;
private MyNetworkResponse callback;
YoutubeUsage(Object caller) {
this.callback = (MyNetworkResponse) caller;
queue = Volley.newRequestQueue((Context) caller);
}
static String getUrl(String signal) {
String playlistId = signal.substring(signal.indexOf("=") + 1);
return "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails%2C%20snippet%2C%20id&playlistId=" + playlistId + "&maxResults=25&key=" + "API_KEY";
}
void fetch(String url){
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.goodResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.badResponse(error);
}
});
queue.add(request);
}
}
ConvertActivity.java
public class ConvertActivity extends AppCompatActivity implements MyNetworkResponse {
YoutubeUsage youtubeUsage;
ArrayList<String> videoIDs = new ArrayList<>();
ListView listView;
MyCustomAdapter myCustomAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_convert);
listView = findViewById(R.id.listview_convert);
youtubeUsage = new YoutubeUsage(this);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
String url = YoutubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
youtubeUsage.fetch(url);
}
}
private ArrayList<String> getVideoIDs(String serverResponse) throws JSONException {
ArrayList<String> rawVideoIDs = new ArrayList<>();
JSONObject jsonObject = new JSONObject(serverResponse);
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject jsonVideoId = jsonObject1.getJSONObject("contentDetails");
rawVideoIDs.add(jsonVideoId.getString("videoId"));
}
return rawVideoIDs;
}
private void createRecyclerView(ArrayList<String> videoIDs) {
myCustomAdapter = new MyCustomAdapter(this, videoIDs);
listView.setAdapter(myCustomAdapter);
myCustomAdapter.notifyDataSetChanged();
}
#Override
public void goodResponse(String responseString) {
Log.d("Convert:goodResp", "[" + responseString + "]");
try {
ArrayList<String> rawVideoIDs = getVideoIDs(responseString);
createRecyclerView(rawVideoIDs);
} catch (JSONException e) {
// handle JSONException, e.g. malformed response from server.
}
}
#Override
public void badResponse(VolleyError error) {
// handle unwanted server response.
}
}
Is there a way to catch and log badrequest or unauthorized response code from an action in web api 2?
I tried adding onactionexecuted attributefilter and ExceptionLogger but neither of them worked.
public IHttpActionResult ConfirmUpload(string val)
{
if (String.IsNullOrWhiteSpace(val))
return BadRequest(val);
}
public static void Register(HttpConfiguration config)
{
AreaRegistration.RegisterAllAreas();
config.Filters.Add(new ErrorLogAttribute());
config.Services.Add(typeof(IExceptionLogger), new ErrorLogger());
}
Any help is appreciated.
To log bad requests you can write your own LogAttribute derived from ExceptionFilterAttribute
public class LogAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
Log.Error(context.Exception);
context.Response = context.Request.CreateResponse(
HttpStatusCode.InternalServerError,
new { message = context.Exception.InnerException != null ? context.Exception.InnerException.Message : context.Exception.Message });
base.OnException(context);
}
}
HttpActionExecutedContext contains information about request so you can check request status, if you need. Attribute can be applied to controller, action
public class ValueController : ApiController
{
[Log]
public IEnumerable<object> Get()
{
}
}
or added globally
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new LogAttribute());
}
}
also all exceptions could be catched in global.asax
protected void Application_Error()
{
var ex = Server.GetLastError().GetBaseException();
// ignore 404
if (!(ex is HttpException && ((HttpException)ex).GetHttpCode() == 404))
{
Log.Fatal("Unhandled error catched in Global.asax", ex);
}
Server.ClearError();
}
After checking the condition if the condition fails then using request dispatcher iam redirecting it to some other page.It is redirecting to that page but the css is not applying to that page.Why is it so?
public class RolePrivilegeFilter implements Filter {
List<String> privilege = null;
private static final String notAuthorizedPath = "/home/notAuthorized.jsf";
#Override
public void destroy() {
log.info("filter finish");
}
#Override
public void doFilter(ServletRequest sRequest, ServletResponse sResponse, FilterChain filterChain) throws IOException, ServletException {
String smUser = null;
try {
HttpServletRequest request = (HttpServletRequest) sRequest;
HttpServletResponse response = (HttpServletResponse) sResponse;
HttpSession session = null;
try {
request = (HttpServletRequest) sRequest;
smUser = request.getHeader(EnvironmentBean.SESSION_ATTR_SM_USER);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
if (rolePrivilege == null || rolePrivilege.isEmpty()) {
rolePrivilege = new RolePrivilegeBuilderImpl().rolePrivilege("Smtest2");
privilege filter bean is\t"+rolePrivilege);
log.debug("After rolePrivilege: " + rolePrivilege);
if (rolePrivilege != null && rolePrivilege.size() > 0 ) {
if (session == null) {
session = request.getSession(true);
}
session.setAttribute("privilege", rolePrivilege);
} else {
//This is the page iam redirecting to.
System.out.println("role privilege not authorized page");
RequestDispatcher rd = request.getRequestDispatcher(notAuthorizedPath);
rd.forward(request, response);
return;
}
} catch (Exception e) {
e.printStackTrace();
log.debug("Error in setting session attribute: " + e.getMessage());
}
log.debug("doFilter() finish");
filterChain.doFilter(sRequest, sResponse);
}
#Override
public void init(FilterConfig arg0) throws ServletException {
log.info("filter start");
}
}
The problem is iam redirecting to that page but the css to that page is not being applied like background image not getting displayed.Why is it so?
Apparently the filter's URL pattern did also match the browser's request for that CSS file and thus it has also been blocked by the filter. Apparently you've mapped the filter on a too broad URL pattern like as /* or something.
You need to ensure that the filter bypasses all those CSS file requests. If there's no way to change the filter's URL pattern accordingly so that it bypasses CSS file requests, e.g. changing /* to /app/* so that it only runs on requests in /app folder where all restricted resources are, then you need to rewrite the filter's code to add an extra check on the request URI.
Something like this:
if (request.getRequestURI().endsWith(".css")) {
chain.doFilter(request, response);
return;
}
This will let all *.css requests be passed instead of being blocked.
I wrote an IHttpModule that compress my respone using gzip (I return a lot of data) in order to reduce response size.
It is working great as long as the web service doesn't throws an exception.
In case exception is thrown, the exception gzipped but the Content-encoding header is disappear and the client doesn't know to read the exception.
How can I solve this? Why the header is missing? I need to get the exception in the client.
Here is the module:
public class JsonCompressionModule : IHttpModule
{
public JsonCompressionModule()
{
}
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += new EventHandler(Compress);
}
private void Compress(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;
try
{
//Ajax Web Service request is always starts with application/json
if (request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json"))
{
//User may be using an older version of IE which does not support compression, so skip those
if (!((request.Browser.IsBrowser("IE")) && (request.Browser.MajorVersion <= 6)))
{
string acceptEncoding = request.Headers["Accept-Encoding"];
if (!string.IsNullOrEmpty(acceptEncoding))
{
acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture);
if (acceptEncoding.Contains("gzip"))
{
response.AddHeader("Content-encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("deflate"))
{
response.AddHeader("Content-encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
}
}
}
}
catch (Exception ex)
{
int i = 4;
}
}
}
Here is the web service:
[WebMethod]
public void DoSomething()
{
throw new Exception("This message get currupted on the client because the client doesn't know it gzipped.");
}
I appriciate any help.
Thanks!
Even though it's been a while since you posted this question, I just had the same issue and here's how I fixed it:
In the Init() method, add a handler for the Error event
app.Error += new EventHandler(app_Error);
In the handler, remove Content-Type from the Response headers and set the Response.Filter property to null.
void app_Error(object sender, EventArgs e)
{
HttpApplication httpApp = (HttpApplication)sender;
HttpContext ctx = HttpContext.Current;
string encodingValue = httpApp.Response.Headers["Content-Encoding"];
if (encodingValue == "gzip" || encodingValue == "deflate")
{
httpApp.Response.Headers.Remove("Content-Encoding");
httpApp.Response.Filter = null;
}
}
Maybe there's a more elegant way to do this but did the trick for me.