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

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.

Related

ActionFilterAttribute for Twilio RequestValidation example not working - why?

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?

importing dart code from other projects

** This question is edited and cleaned up some **
I have two projects and I want to use code from one in the other; I seem to be having trouble putting the code in the right directory structure to make the import statements work.
Both projects are created and managed exclusively from the Dart Editor on a Mac, if that makes any differences.
Project Directory Structures
Project 1: a command line app which contains the code I want to share in the following directory structure:
/dart/command_line_app
/lib
shared_library.dart
/bin
command_line_app.dart
Project 2: a web app which wants to import the code in shared_libary.dart
/dart/web_application
/packages
/web
web_application.dart
In the file shared_libary.dart, I declare it to be a library can create a simple class that provides output when instantiated:
library shared_library;
class ShareMe
{
ShareMe()
{
print("Hello, ShareMe");
}
}
This compiles, and works inside the command_line project: command_line_app.dart has the following:
import 'package:command_line_app/shared_library.dart';
void main() {
ShareMe shareMe = new ShareMe();
print("Hello, World!");
}
This imports the code runs, printing both "Hello Share Me," and Hello World.
THE PROBLEM
I want to instantiate the ShareMe class inside web_application.dart. I'd thought I could do that by putting in the same import statement I put in my command_line code:
import 'package:command_line_app/shared_library.dart';
But, when I put the same import into the web_appliation, it gets the error
Target of URI does not exist 'package:command_line_app/shared_library.dart'
Other Things I've Tried
I was certain I'd solved the problem when I cntrl-Clicked properties on Web_application and selected Project References.
It brings up a window allowing me to select command_line_app with a check box, but when I do, I get an error:
Could not set the project description for 'web_application' because the project description file (.project) is out of sync with the file system.
Whatever that means.
When I cntrl-click the underlined error and try Quick Fix it offers me "resolve dependencies" which sounds promising, but after a few seconds, it comes back and informs me that
Pub get failed, [1] Resolving dependencies... (15.3s)
Could not find package command_line_app at https://pub.dartlang.org.
Depended on by:
- web_application 0.0.0
I hope this is clear-er and gives a better insight into both what I'm trying to do and what I'm missing.
EDIT
you need to add
dependencies:
command_line_app:
path: ../command_line_app
to your dependencies in web_application/pubspec.yaml.
EDIT END
When you want to make code reusable in different packages, you should put that code into the lib directory of that package and import it using import 'package:mypackage/myfile.dart';.
Another problem you may face is, that browser applications can't import packages that have a dart:io dependency. If you want to reuse code between command line and browser applications you should move them into the lib directory of another package my_shared_code where you put only code that doesn't depend on dart:io (for example some entity classes) and import this code from both app packages (browser and command line).

How can I create a directory in my source control using TFS 2010 SDK?

I want to customize the creation of a TFS project using TFS 2010 SDK.
I have already create a process template and use this sample, but I want to create a specific directory tree for the new team project base on a XML file which describe the tree. My problem is this message; The array must contain at least one element.
Parameter name: checkinParameters.PendingChanges
I initialize the TFS, map the server folder with a local folder and create directories in both.
fooString = Array.Find<WorkingFolder>(workspace.Folders, m => m.ServerItem.Contains("$/FR_DEV"));
Directory.CreateDirectory(ElementPath);
Directory.CreateDirectory(fooString.ServerItem + ElementTfsPath);
After that:
PendingChange[] PendingChanges = workspace.GetPendingChanges();
// Checkin the items we added
int changesetForAdd = workspace.CheckIn(PendingChanges, "Project creation.");
However, I get an error for the pending change! How can I fix this?
my problem was that i need to add the directory in the workspace not with a simple path
workspace.PendAdd(currentSubDirectory, true);

Programmatically Add Files To TFS with dependency files

How can I programmatically add files to a TFS project that have code behind files. I can say the following to add files. That will only add single files to a project and not the file plus the code behind file. I'm trying to add a resource file and it's code behind that were dynamically generated to a TFS project.
workspace.PendAdd(filesWithPathToEdit, true);
I had to put it in a T4 template to get access to the current Visual Studio DTE otherwise it would randomly work if I tried it outside of a t4. You can use the DTE to get a list of projects from a solution then add a ProjectItem and it contains ProjectItems so you can add your code behind there. ResxContainer is a custom class to just contain all information about my resx file i needed.
EnvDTE.DTE dte = (EnvDTE.DTE)HostServiceProvider.GetService(typeof(EnvDTE.DTE));
//dte = (EnvDTE.DTE) hostServiceProvider.GetService(typeof(EnvDTE.DTE));
//dte = (EnvDTE80.DTE2)Marshal.GetActiveObject("VisualStudio.DTE");
Projects projects = dte.Solution.Projects;
if (projects.Count > 0)
{
IEnumerator enumer = ((IEnumerable)projects).GetEnumerator();
while (enumer.MoveNext())
{
Project proj = (Project)enumer.Current;
if (proj.Name == projectName)
{
foreach (ResxContainer res in items)
{
ProjectItem item = proj.ProjectItems.AddFromFile(res.ResxPath);
item.ProjectItems.AddFromFile(res.CodeBehindPath);
}
}
}
There's no way for it to automatically know if a file depends on another. However, you can decide on your own which files will typically have a code behind file associated with them and add them yourself.
For example:
If you begin to add a file with an .aspx extension, then those files, as we know, typically have a code behind file. That code behind file, we can assume, has the same file name, with .cs appended. So, if we have "Default.aspx", then we can safely assume that there will be a "Default.aspx.cs" and that they are dependent on each other, so we should add both.
The same thing goes with .xaml and .xaml.cs files.

How do you SetMaxAttachmentSize in TFS 2010?

I want to set the maximum work item attachment size. From old blogs I have found that it is possible by calling SetMaxAttachmentSize, but the blogs are for older versions of TFS. I have found the new webservice path for TFS 2010.
http://localhost:8080/tfs/_tfs_resources/WorkItemTracking/v1.0/ConfigurationSettingsService.asmx/SetMaxAttachmentSize
Unfortunately when I call it like that I receive this error: This request can only be made against a project collection. The (.asmx) file should be located in the project directory (usually _tfs_resources under the application root).
I don't know how to format the call via a browser to target a specific project collection. Any thoughts?
Apparently SetMaxAttachmentSize web service was not leveraged on TFS 2010 therefore you need to do this programmatically, try running the following code:
TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(#"http://yourtfsserver:8080/tfs/DefaultCollection");
ITeamFoundationRegistry rw = tfs.GetService<ITeamFoundationRegistry>();
RegistryEntryCollection rc = rw.ReadEntries(#"/Service/WorkItemTracking/Settings/MaxAttachmentSize");
RegistryEntry re = new RegistryEntry(#"/Service/WorkItemTracking/Settings/MaxAttachmentSize", "20971520"); //20MB
if (rc.Count != 0)
{
re = rc.First();
re.Value = "20971520";
}
rw.WriteEntries(new List<RegistryEntry>() { re });
I hope it works for you
Regards,
Randall Rosales
I have found that this works. It is easier than writing code.
Go to this url replacing <Collection> with your project collection: http://localhost:8080/tfs/<Collection>/WorkItemTracking/v1.0/ConfigurationSettingsService.asmx
Choose SetMaxAttachmentSize
You can test to make sure you set it correctly by going to the same url above and then selecting GetMaxAttachmentSize.

Resources