ActionFilterAttribute for Twilio RequestValidation example not working - why? - asp.net-mvc

First, I'm newish to MVC so bear with me. I'm following the Twilio example located here to validate that status callbacks from Twilio are authentic: https://www.twilio.com/docs/usage/tutorials/how-to-secure-your-csharp-aspnet-app-by-validating-incoming-twilio-requests#create-a-custom-filter-attribute
The code provided as-is should be reviewed by Twilio as the constructor name has a typo in it as they have "RequestAttribute" in it twice.
My issue is that I cannot for the life of me get the Attribute to resolve when I place it on my controller. I noticed the example Action Filter has a namespace ending ".Filters" and I noticed that my MVC application does not have a "Filters" directory. Some googling indicated that may be a difference between MVC4 and 5 - from what I can tell I'm using MVC5 as that's the listed version number on the System.Web.Mvc reference (version 5.2.2.0 specifically if that matters).
Anyway, Twilio linked to Microsoft documentation on creating the Custom Action Filter here: https://learn.microsoft.com/en-us/previous-versions/aspnet/dd410056(v=vs.98)?redirectedfrom=MSDN
Microsoft suggests creating the Action Filter class directly in the "Controllers" directory - so that's where I placed mine. Here is how that class reads currently:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Twilio.Security;
using System.Net;
using System.Web.Mvc;
using System.Web.Mvc.Filters;
namespace SMSStatusWS.Controllers
{
public class ValidateTwilioRequestAttribute : System.Web.Mvc.ActionFilterAttribute
{
private readonly RequestValidator _requestValidator;
public ValidateTwilioRequestAttribute()
{
var authToken = "<--------REMOVED------->";
_requestValidator = new Twilio.Security.RequestValidator(authToken);
}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
var context = actionContext.HttpContext;
if (!IsValidRequest(context.Request))
{
actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
}
base.OnActionExecuting(actionContext);
}
private bool IsValidRequest(HttpRequestBase request)
{
var signature = request.Headers["X-Twilio-Signature"];
var requestUrl = request.Url.AbsoluteUri;
return _requestValidator.Validate(requestUrl, request.Form, signature);
}
}
}
Then my attempt to use it...
[HttpPost]
[ValidateTwilioRequest ]
public ActionResult UpdateSmsStatus(string dbContext, string smsQueueId)
{
// Controller code here...
}
The attribute [ValidateTwilioRequest ] is highlighted in red in Visual Studio... meaning it can't resolve it (I guess) but I'm not sure why as the namespace is the same in both my controller class and the action filter class...
namespace SMSStatusWS.Controllers
So at this point, I'm not sure what's wrong here. As far as I can tell, the custom action filter was created correctly, and I'm using it as Twilio shows, but yet it doesn't work. Even though the filter does not seem to resolve, the project builds and runs... but of course it never hits the code in the action filter.
Is there some other way I need to reference this Action Filter that the docs are not telling me? Thoughts on what to try or look for that I may be overlooking?
UPDATE 10/13/21:
I have made some progress... turns out the attribute not resolving was related to Visual Studio. Not able to figure out why it wasn't resolving, I closed the solution and restarted Visual Studio and when I reopened it, it started resolving the attribute immediately. However, I'm not positive it's working as I can't hit a breakpoint in the OnActionExecuting override and Visual Studio says no symbols have loaded.
So new question now, how do you debug custom Action Filters? Shouldn't I be able to step into the code with the debugger?

You could you try using System.Diagnostics.Debug.WriteLine in the OnActionExecuting function and using that rather than the break point. That should write out to the output window and let you know if that code is running. After adding that code your OnActionExecuting function would look like this.
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
string controller = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
string action = actionContext.ActionDescriptor.ActionName;
System.Diagnostics.Debug.WriteLine("Controller-" + controller + ", Action-" + action);
var context = actionContext.HttpContext;
if (!IsValidRequest(context.Request))
{
actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
}
base.OnActionExecuting(actionContext);
}

Wow... learned a bit about Visual Studio and debugging today.The MVC project I have created for all of this had the project output set to a bin directory 2 levels up from my project. I'll call this the "global bin" - we use our global bin as a place for a lot of other projects to write their output to and that one location is referenced in our nightly build.
What I noticed is that my local project bin directory had an old DLL and PDB file in it, presumably from a build prior to changing the output directory to our global bin (global bin has the current dll and pdb). When debugging, I would notice that the debugger would load the dll and pdb from the "Temporary Asp.Net files" path (you can find this info in the "Module" window while debugging in Visual Studio) - this temp directory had those same old versions of the pdb in it and that is ultimately why I was unable to debug my Action Filter Attribute - it had an outdated pdb that did not have symbols for my latest code changes in it.
My band-aid for now is to set the output directory of my Project back to it's own local bin directory, and in web.config, disable shadowCopyBinAssemblies - which prevents the debugger from using the outdated pdb in the Temporary Asp.Net files directory and instead uses the pdb in the local bin.
That looks like this in web.config...
<system.web>
<hostingEnvironment shadowCopyBinAssemblies="false"/>
<system.web
I'm confused as to why Visual Studio doesn't shadowCopy the dll and pdb from our defined global bin (when it's defined as the project's output directory) to the Temporary Asp.Net files directory. That would solve all of this but I don't know if that can be configured anywhere.
As soon as I changed this to output to the project's bin directory and disabled the shadowCopy in web.config, the debugger loaded symbols from the correct dll and pdb and my breakpoints hit immediately.
I guess I'll add a post-build event or something to copy the dll & pdb files to our global bin so this doesn't break our nightly build, but this feels like a hack. If the default shadowCopy settings for the Temporary Asp.Net Files directory can't be changed I don't know what else to do about it. Is this a Visual Studio bug perhaps... shadowCopying from the project bin always, even if the output is configured to be written elsewhere?

Related

Calling Another Project's Controller From A Project In The Same Solution (.NET Core )

There are 2 projects in the same solution. First project is a .NET Core project and it has all the codes(controllers, models etc.) related to packages. I need to get the information (id, name, description) of the packages and display it in the second project(.NET Core Web App with Razor). Is it possible to do it without changing the first project? I only want to show the package list on a single web page.
I tried calling the first project's controller but it didn't work. Maybe I missed a point. Any help is appreciated.
This requirement can be achieved, please see the gif image below.
Tips
If you want to call another project's controller from a project in the same solution, you need to make sure there is in HomeController in both project. I mean the name of any class should be unique in both projects.
Otherwise you will face the same issue like my homepage.
Test Code:
public List<PackageReference> GetPackageList5(string projectname)
{
List<PackageReference> list = new List<PackageReference>();
PackageReference p = null;
XDocument doc = XDocument.Load(_webHostEnvironment.ContentRootPath+ "/"+ projectname + ".csproj");
var packageReferences = doc.XPathSelectElements("//PackageReference")
.Select(pr => new PackageReference
{
Include = pr.Attribute("Include").Value,
Version = pr.Attribute("Version").Value
});
Console.WriteLine($"Project file contains {packageReferences.Count()} package references:");
foreach (var packageReference in packageReferences)
{
p = new PackageReference();
p.Version= packageReference.Version;
p.Include= packageReference.Include;
list.Add(packageReference);
//Console.WriteLine($"{packageReference.Include}, version {packageReference.Version}");
}
return list;
}
My Test Steps:
create two project, Net5MVC,Net6MVC
add project reference.
My .net6 project references a .net5 project. So in my HomeController (.net), I add below:
using Net5MVC.ForCore6;
using Net5MVC.Models;
Suggestion
When we reference the .net5 project in .net6 project, we can build success, but when we deploy it, it always failed. The reason is some file was multiple publish output files with the same relative path.
Found multiple publish output files with the same relative path:
D:\..\Net6\Net6\Net5MVC\appsettings.Development.json,
D:\..\Net6\Net6\Net6MVC\appsettings.Development.json,
D:\..\Net6\Net6\Net5MVC\appsettings.json,
D:\..\Net6\Net6\Net6MVC\appsettings.json.
And usually will add class library to current project, not add a web project.
As we know we can find packages info in .csproj file, so we need copy and paste .csproj file to publish folder.
I still recommend using the GetPackageList5 method above as an interface for your project, using HttpClient for requests.

Kentico 12 PageBuilder missing reference

In the _Layout.cshtml page, I receive this exception (IFeatureSet' does not contain a definition for 'PageBuilder' and no accessible extension method 'PageBuilder' accepting a first argument of type 'IFeatureSet' could be found).
Here is my code.
#{
var editMode = string.Empty;
if (HttpContext.Current.Kentico().PageBuilder().EditMode)
{
editMode = "kentico-page-builder";
}
}
The project won't build because of it. The project has been upgraded to Kentico 12.0.30 even though the dll version says 12.0.0 (See attached image)
I have restarted Visual Studio, my computer, cleared temp files, cleared cache. Nothing fixes it. Anyone have any ideas why?
The PageBuilder() extension method is located in the Kentico.PageBuilder.Web.Mvc namespace, so you need to add this to your view:
#using Kentico.PageBuilder.Web.Mvc
Or, you can follow the guidance in #3 in the Registering the page builder section on https://docs.kentico.com/k12/developing-websites/page-builder-development and register the namespace in the web.config of the /Views folder:
<add namespace="Kentico.PageBuilder.Web.Mvc"/>

Xamarin add-in reference installation location

I am writing a plugin that adds a project template. This template needs to use some files that the default templates use too.
I am looking for something like the ${ProjectName} variable but for the installation folder. Does something like this exist or is there some other workaround I can use?
Here is
<Files>
<Directory name="Resources">
<RawFile name="Default.png" src="${Reference To Installation Folder}/Templates/iOS/Default.png" />
<RawFile name="Default#2x.png" src="${Reference To Installation Folder}/Templates/iOS/Default#2x.png" />
</Directory>
</Files>
By installation folder I am assuming you mean where Xamarin Studio is installed.
I am also assuming that you cannot distribute the files with your addin since they are part of Xamarin Studio and not available with just MonoDevelop.
There is no property/parameter that specifies where Xamarin Studio is installed as far as I am aware.
The src attribute in RawFile does not support having parameters being replaced so even if there was a parameter which pointed to where Xamarin Studio was installed it could not be used.
So you are left with two options that I can think of:
Implement a wizard for your project template.
Implement your own RawFile template.
A project template wizard would mean you could only support Xamarin Studio 5.9 and above. So I will ignore this for now. Both the above options are similar in how they are implemented.
For your own version of the RawFile template you define the class to use in your addin.xml file:
<Extension path = "/MonoDevelop/Ide/FileTemplateTypes">
<FileTemplateType name = "RawFileNoExtension" class = "MyAddin.MyRawFileExtensionTemplate"/>
</Extension>
Then you can create your own file extension template class. Here is an example taken from the existing RawFileDescriptionTemplate but I have removed some error handling:
public class MyRawFileExtensionTemplate : RawFileDescriptionTemplate
{
FilePath contentSrcFile;
public override void Load (XmlElement filenode, FilePath baseDirectory)
{
base.Load (filenode, baseDirectory);
var srcAtt = filenode.Attributes["src"];
// TODO: Replace src with path to Xamarin Studio.
contentSrcFile = FileService.MakePathSeparatorsNative (srcAtt.Value);
contentSrcFile = contentSrcFile.ToAbsolute (baseDirectory);
}
public override Stream CreateFileContent (SolutionItem policyParent, Project project, string language,
string fileName, string identifier)
{
return File.OpenRead (contentSrcFile);
}
}
You would need to replace the TODO section with code to find where Xamarin Studio is installed. One way to do that would be to find a type in one of Xamarin Studio's assemblies and then get the assembly's location.

Custom script transform in ASP.NET MVC bundle ignored when debug is false and minified file exists

I'm working on an MVC 5.0 (.Net 4.5) application where I need to apply a custom JavaScript transform to my included bundle files. One of those files, which I'm calling dummy.js for illustration purposes, has a minified file called dummy.min.js.
I created a custom script transform to replace injected window.jQuery references with a different expression. Everything works fine when I run locally and in debug mode, but when debug mode is turned off in the Web.config file, the Bundle returns the contents of the dummy.min.js file, but my script transform is not applied to it. It only gets applied to JavaScript files that don't have an associated .min.js file.
Does anyone have an idea on how to resolve this? It almost sounds like a bug in MVC.
A workaround is to remove the minified file. This post kind of addresses my situation by suggesting removing the .min.js file since MVC minifies by default, but I'm looking for an alternative solution (if any).
Thank you so much in advance.
Here's how to reproduce the above:
If you're interested in reproducing my issue, here's a quick BundleConfig and the actual custom script transform. It replaces all instances of window.jQuery with window.$jq1_9||window.jQuery, assuming it is injected via a self-executing anonymous function.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(
new ScriptBundle("~/bundles/dummy")
.Include("~/Scripts/dummy.js", new InjectedJQueryVariableRewriteTransform()));
}
}
public class InjectedJQueryVariableRewriteTransform : System.Web.Optimization.IItemTransform
{
public string Process(string includedVirtualPath, string javaScriptCode)
{
// TODO: I understand this approach is naiive, but it does the trick for now.
return javaScriptCode.Replace("window.jQuery", "window.$jq1_9 || window.jQuery");
}
}
If you have Visual Studio 2012 and MVC 4, you will need version 1.1.0 of the System.Web.Optimization assembly, which you can obtain by running the following command in the Nuget Package Manager. At time of writing it installs version 1.1.2 of the package.
Install-Package Microsoft.AspNet.Web.Optimization
Here's the sample JavaScript dummy.js. You can create a copy of it and name it dummy.min.js:
(function ($) {
"use strict";
// TODO: Do something interesting...
})(window.jQuery);
Set the debug attribute to false in the following element in Web.config:
<compilation debug="false" targetFramework="4.5" />
Assuming the application's port is 9221, render the bundle in Firefox or Chrome:
http://localhost:9221/bundles/dummy
You will see that when debug is set to true, the transform is applied, as shown below:
(function(){"use strict"})(window.$jq1_9||window.jQuery)
When it is set to false. It is ignored and only the .min.js file is used:
(function(){"use strict"})(window.jQuery)
If you add this line:
bundles.FileExtensionReplacementList.Clear();
you will remove the rule for using .min files when bundling is enabled. You will remove all rules, unfortunately, so if you need any of the other ones you'll need to add them manually. Also, this will change the rules for all bundles.
If you just want to disable these replacement rules for just one bundle, you can just set the EnableFileExtensionReplacements property to false on that specific bundle:
var bundle = new ScriptBundle("...");
bundle.EnableFileExtensionReplacements = false;

MVC DoddleReports 404 Not Found

I have recently, as in about an hour ago, tried to implement the DoddleReports functionality into my MVC application.
Pretty positive I followed the documentation to the T. However, when I go to input my URL it gives me a 404 not found. I installed the packages via NuGet and I only need Excel so I added OpenXML (along with the dependencies).
My controller:
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using VAGTC.Models;
using VAGTC.ViewModels;
using VAGTC.Helpers;
using DoddleReport.Web;
using DoddleReport;
namespace VAGTC.Controllers
{
public class reportsController : Controller
{
//
// GET: /Excel/
VAGTCEntities db = new VAGTCEntities();
public ActionResult Index()
{
return View();
}
public ReportResult OrganizationReport()
{
var matrix = from d in db.Organizations
select d;
var report = new Report(matrix.ToReportSource());
return new ReportResult(report);
}
}
}
The RouterConfig:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using DoddleReport.Web;
namespace VAGTC
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapReportingRoute();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
}
}
}
When I installed Doddle with NuGet - it also automatically inputted the stuff needed in the web.config (not the web.config in the View folder!). I read a comment, right here, in the documentation for configuring Doddle with MVC and replaced the code. (but it also didn't work with code that was auto-generated). I didn't get fancy with customizing anything yet as I just wanted to get it working first!
So, how come the 404 page is coming up? It makes me seem it is something with routing but I am unsure of what specifically.
Any help is greatly appreciated!
I am using it in debug mode - so maybe that could be a reason? This is the link I am using:
EDIT* Uploaded to my site and still gives a 404.
http://localhost:2530/reports/OrganizationReport.xls
EDIT 2*
After messing around, and changing a couple things according to the forum post given by #fiorebat. I debugged it right after it generates the report, var report = new Report(matrix.ToReportSource()); and it gives this error once it returns the report.
No Source Available
There is no source code available for the current location.
Call stack location:
DoddleReport.dll!DoddleReport.ReportBuilder.ToReportSource(System.Collections.IEnumerable source) Line 12
Source file information:
Locating source for 'c:\Users\Matt\Development\Projects\DoddleReport\src\DoddleReport\ReportBuilder.cs'. Checksum: MD5 {61 dc e5 8e 25 79 c2 94 c4 27 5b d0 d7 92 56 ae}
The file 'c:\Users\Matt\Development\Projects\DoddleReport\src\DoddleReport\ReportBuilder.cs' does not exist.
Looking in script documents for 'c:\Users\Matt\Development\Projects\DoddleReport\src\DoddleReport\ReportBuilder.cs'...
Looking in the projects for 'c:\Users\Matt\Development\Projects\DoddleReport\src\DoddleReport\ReportBuilder.cs'.
The file was not found in a project.
Looking in directory 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\crt\src\'...
Looking in directory 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\crt\src\vccorlib\'...
Looking in directory 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src\mfc\'...
Looking in directory 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src\atl\'...
Looking in directory 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\include'...
Looking in directory 'C:\'...
The debug source files settings for the active solution indicate that the debugger will not ask the user to find the file: c:\Users\Matt\Development\Projects\DoddleReport\src\DoddleReport\ReportBuilder.cs.
The debugger could not locate the source file 'c:\Users\Matt\Development\Projects\DoddleReport\src\DoddleReport\ReportBuilder.cs'.
You need to add under the system.webServer in the web config this configuration:
<modules runAllManagedModulesForAllRequests="true" ></modules>
I have same issue, report without extension works, i debug the route with "RouteDebuggin" and it's working. Seems that DoodleReport plugin don't calls the correct action.
http://doddlereport.codeplex.com/discussions/348486

Resources