Is there a tool in VS2015 to debug webapi routes? - asp.net

In Visual Studio 2015 (Enterprise), is there still no built-in tool that will dissect and display the routing information for WebAPI calls?
WebApi Route Debugger does not seem to work for ASP.NET 5 (and mangles the default Help page in the template)
Glimpse does not offer the "Launch Now!" button anymore from what I can tell (http://blog.markvincze.com/use-glimpse-with-asp-net-web-api/).

RouteDebugger is good for figuring out which routes will/will not be hit.
http://nuget.org/packages/routedebugger but you are saying it doesn't work. After some googling I found another solution to your problem,
Add an event handler in Global.asax.cs to pick up the incoming request and then look at the route values in the VS debugger. Override the Init method as follows:
public override void Init()
{
base.Init();
this.AcquireRequestState += showRouteValues;
}
...
protected void showRouteValues(object sender, EventArgs e)
{
var context = HttpContext.Current;
if (context == null)
return;
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(context));
}
Then set a breakpoint in showRouteValues and look at the contents of routeData.
Keep in mind that in a Web Api project, the Http routes are in WebApiConfig.cs ... not RouteConfig.cs
but that's not a tool. may be digging up some thread would help you resolve your issue.
Reference: Is there a way I can debug a route in ASP. MVC5?

Related

ASP.NET MVC, Is it possible to code a Response.AppendToLog in one place which will act on every Request?

I am using ASP.NET 4.7 and MVC5 with C# with IIS Express locally and published to Azure App Services.
I want to add something like:
Response.AppendToLog("XXXXX Original IP = 12.12.12.12 XXXXX");
Which adds an Original IP address to the request string in the "request" column in the web server log.
If I add this to a specific "get" Action this works fine. However I do not want to add this code to every Action. Is it possible to place it more centrally such that it gets executed on every "Get" / Request. This may be a simple question, but the answer alludes me at present
Thanks for any wisdom.
EDIT: Is this via Custom Action Filters?
if (filterContext.HttpContext.Request.HttpMethod=="GET")
{
Response.AppendToLog... //I know this will not work as Response not known.
}
You almost know the answer. Try handling OnActionExecuted that gets you the Response.
public class CustomActionFilter : ActionFilterAttribute, IActionFilter
{
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
if(filterContext.HttpContext.Request.Method == HttpMethods.Get)
{
}
}
void IActionFilter.OnActionExecuted(ActionExecutedContext context)
{
var response = context.HttpContext.Response;
}
}
My solution to write out text:
filterContext.RequestContext.HttpContext.Response.AppendToLog("OrigIP");

Too many redirects error (ASP.NET MVC)

I have MVC app and I try to access mobile area.
So I decided to use integrated to chrome mobile mode.
My start controller is Account/Login
Here is code of ApplicationStart
protected void Application_Start()
{
#if DEBUG
XmlConfigurator.ConfigureAndWatch(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logging_DEBUG.config")));
#else
if (AppDomain.CurrentDomain.BaseDirectory.Contains("DevTrackerweb")
|| AppDomain.CurrentDomain.BaseDirectory.Contains("Trackerweb4Test"))
{
XmlConfigurator.ConfigureAndWatch(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logging_DEBUG.config")));
}
else
XmlConfigurator.ConfigureAndWatch(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logging.config")));
#endif
var log = LogManager.GetLogger(AppDomain.CurrentDomain.BaseDirectory);
log.Info("Application start");
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new NullableDecimalModelBinder());
Translator.Prefetch().Wait();
HttpContext.Current.Application.Add("TrackerwebServiceStatus", TrackerwebServiceStatus.OK);
sitesByHostName = InitializeSites();
mainCustomerIDByCustomerID = InitializeCustomerIDDictionary();
}
When I run it, I have this
How I can solve this problem?
My guess is your login page/action is not configured for anonymous access. Try adding the AllowAnonymous attribute to the Login action method.
So problem was in that it was legacy code and I have MvcSiteMap extension ,that I deleted.
In web config I had some code related to this extension and when I deleted it all okay

How to programmatically add actions to application events?

In global.asax we have the possibility to implement methods that corresponds to an application event, for example Application_EndRequest, and add whatever code we want to these.
I'm developing an plugin that have the need to attach to some of these events, is there any way to programmatically push actions for these into the application flow somehow?
The goal is obviously to avoid the need for manually adding code in global.asax when using the plugin.
How to hook an HTTP Module into an MVC application
If I understand you correctly, you want to create an external library and "hook" it up to an MVC application's events.
1. Create a simple class library.
The first thing is to create a simple class library. We'll call it TestLib.
2. Create a new class called TestLibHttpModule.
The class implements IHttpModule. This grants it the Init() method. This method will be called when the module is initialised and it passes us the HttpApplication object that is initialising the module.
In our Init method, we'll attach a new EventHandler to the EndRequest event.
For now, our event handler method will simply throw an exception with a cheeky message.
namespace TestLib
{
public class TestLibHttpModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(context_EndRequest);
}
private void context_EndRequest(object sender, EventArgs e)
{
// get the HttpApplication context
HttpApplication context = (HttpApplication)sender;
throw new NotImplementedException("At least it works.");
}
}
}
3. Point the library's build path to our MVC project.
Assuming you have an MVC project already set up nearby, perhaps called TestApp, point the build path of your library to be the bin folder of your MVC project. Now, every time we build the module, it'll be thrown into the MVC project.
4. Update MVC project to use the HttpModule.
The Web.config of an MVC application has a spot for specifying Http Modules. Under the system.Web element, add a new httpModules section (if it doesn't already exist).
<system.web>
[ ... ]
<httpModules>
<add name="TestLibModule" type="TestLib.TestLibHttpModule, TestLib" />
</httpModules>
</system.web>
5. Run the MVC application.

Session is null in the new page when transfer the request in the HttpModule

All, I'm trying to implement an HttpModule (IHttpModule) to catch pages request and redirect to a new page. Unfortunately, it seems I can't use the Session in the new page. because the Session is null.
Here is my code looks like. please review it .
public class MyModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
....
HttpContext.Current.Server.Transfer("newpage.aspx");//redirect to new page.
}
}
In the newpage.aspx, There is an exception says Object reference not set to an instance of an object for the code HttpContext.Current.Session[xxx], Because the HttpContext.Current.Session is null .
Could someone tell me what happen to it ?
Thanks.
Update
All, I found If I use the HttpContext.Current.Response.Redirect to redirect url . Everything is ok. I mean the Session object is initiated before being used.But that doesn't work for Server.Transfer.
I already knew what is the difference of these two.
The normal aspx runtime pipeline with 2 modules is:
--> HttpModule_1.BeginRequest(); --> HttpModule_2.BeginRequest(); --> HttpHandler(Page)
<-- HttpModule_1.EndRequest(); <-- HttpModule_2.EndRequest(); <-- HttpHandler(Page)
Imagine HttpModule_1 as your custom module and HttpModule_2 as the aspx session module.
Your custom module is running first, so no session is filled in when your module is running.
When HttpModule_1 is running BeginRequest you add a Server.Trasfer(). Now, the server transfer will execute the HttpHandler of the request page immediately, it will be called without leaving the BeginRequest and after the handler is done the transfer method will run the Request.End() and terminate the processing.
So, the handler for the "newpage.aspx" will also run before the session module. (actually, the session module will never run because Server.Transfer() will end the request).
If you guaranty that the session module is processes before your module you should resolve the problem (see https://stackoverflow.com/a/2427632/953144).

Silverlight error while calling a service

I am trying to call a service from a silverlight application, but I am getting the following error.
Uncaught Error: Unhandled Error in Silverlight Application An exception occurred during the operation, making the result invalid. Check InnerException for exception details.
This works fine locally. I don't know if it make any sense, but locally if I add the url of the webservice on a browser, I am getting the details page of the service. In the other hand, on production server, it prompts me to download it.
Does anyone know something about this?
Thanks
public MainPage() {
InitializeComponent();
Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e) {
var newsFeedWcfClient = new NewsFeedWCFClient();
newsFeedWcfClient.GetNewsFeedItemsCompleted += newsFeedWcfClient_GetNewsFeedItemsCompleted;
newsFeedWcfClient.GetNewsFeedItemsAsync();
}
void newsFeedWcfClient_GetNewsFeedItemsCompleted(object sender, GetNewsFeedItemsCompletedEventArgs e) {
var source = (IList<NewsFeed>)e.Result;
IList<CustomNewsFeed> customNewsFeeds = new List<CustomNewsFeed>();
foreach (var item in source) {
customNewsFeeds.Add(new CustomNewsFeed() {
ProductID = item.Products.ProductID,
ProductTitle = item.Products.Title,
Status = item.Text,
Thumb = string.Format("{0}/{1}", item.Products.Product_Photos.Select(pp => pp.PhotoPath).FirstOrDefault(), item.Products.Product_Photos.Select(pp => pp.PhotoName).FirstOrDefault()),
UserID = item.User.Id,
UserName = item.User.Username
});
}
NewsFeedLB.ItemsSource = customNewsFeeds;
}
The fact that on the production server it "prompts you to download" would suggest that the production web server doesn't know what to do with your .svc or .asmx file. It is treating it like a normal file (.txt, .pdf etc).
Have you got all of the required items installed in production. For instance, you need the correct .NET runtime to be installed. Also, ASP.NET needs to be installed and then enabled.
To determine exactly what is happening I would recommend installing Fiddler and using it to trace what is happening when the Silverlight app calls the server. I have found this approach to be invaluable when troubleshooting Silverlight to Web Service communication problems.

Resources