UrlHelper.Action return empty string - urlhelper

very weird problem, I spent hours but not be able to find what exactly the problem is.
I have some code as follows:
public static string AbsoluteAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues)
{
return ResolveUrl(urlHelper, urlHelper.Action(actionName, controllerName, routeValues));
}
private static string ResolveUrl(UrlHelper urlHelper, string relativeUrl)
{
return new Uri(GetRequestUri(urlHelper), relativeUrl).AbsoluteUri;
}
private static Uri GetRequestUri(UrlHelper urlHelper)
{
return urlHelper.RequestContext.HttpContext.Request.Url;
}
When using string.Empty as routeValues, "urlHelper.Action(actionName, controllerName, routeValues)" works well on my local dev machine. (Windows 7, IIS 7.5, .Net 4.0, MVC3) It returns correct url.
But it returns empty string on our continuous integration server. (Windows server 2008, IIS 7.0, .Net 4.0, MVC3)
This is the route configuration:
routes.MapRoute(
"MyRouteName",
"getaddresses/{postcode}/",
new { controller = "Address", action = "GetAddresses", postcode = string.Empty },
new { httpMethod = new HttpMethodConstraint("GET") }, new[] { "My.Package.Controllers" });
If I use some string rather than string.Empty as RouteValues, it works well on both machines.
It seems that the issue is caused by different configurations or different version of tools or frameworks on dev machine and CI machine. Does anybody can help?
For you to better understand this issue, this is the context:
The team is using .Net 3.5, Visual Studio 2010, MVC2. I upgraded them to .Net 4.0, Visual Studio 2012, MVC3. Everything is fine on my local dev machine. I installed .Net 4.0 and MVC3 on CI server (Not same installation files to dev machine, because they are installed along with visual studio). The website is running well on CI server. The only problem is that one smoke test is failed, which expects "localhost/getaddresses" is returned when calling AbsoluteAction("action name", "controller name", new {postcode=string.Empty} ), but it is actually "localhost"
Hope I have well described the issue. : )
Many thanks!

Related

.net framework 4.7.2 broke httpclient

My ASP.NET MVC project used HttpClient.PostAsync() to post to a webAPI endpoint. All is fine until I recently upgraded the project to target .NET Framework 4.7.2. Now the call will end with HTTP Status 405 (Method not allowed). However, endpoints with [HTTPGet] work. In a desperate measure, I set the API controller with [EnableCors(origins: "", headers: "", methods: "*")] and call the endpoint with the same domain and port (localhost to localhost). I even reverted the project to 4.6.1. It still throws 405 error. Could you help? Thank you.
public static async Task < T > Post < T > (string baseUrl, string urlSegment, HttpContent postContent) {
string responseContent = string.Empty;
Uri returnUrl = null;
using(HttpClient client = GetClient(baseUrl)) {
HttpResponseMessage response = await client.PostAsync(urlSegment.TrimStart('/'), postContent).ConfigureAwait(false);
if (response.IsSuccessStatusCode) {
returnUrl = response.Headers.Location;
}
return JsonConvert.DeserializeObject < T > (returnUrl.ToString());
}
}
It turned out that the WebAPI endpoint path has been changed. In addition, I reverted the GIT commit to rollback to a version before I upgrade to DotNet Framework 4.7.2, then cherry-picked all the commits after the 4.7.2 upgrade.

Kestrel Server trucating Request.Host to just subdomain

The title says it all. I'm running asp core app in azure. I'm noticing that Request.Host only returns the subdomain portion.
Can't tell of this is an azure implementation issue or Kestrel or asp core.
For example the following controller running on [mysubdomain].azurewebsites.net
[Route("busted")]
public Dictionary<string, object> Index()
{
var dict = new Dictionary<string, object>();
dict.Add("Request.Host", Request.Host);
return dict;
}
would return
{
"Request.Host" : "mysubdomain"
}
I believe the issue was an azure configuration or something because the issue has resolved this morning without code changes.

SSRS Report Viewer: request failed with HTTP status 401

I've spent a lot time trying to figure this one out, but without luck - so I will try to post the question here.
I am running 2 ASP.NET websites on the same server. Both websites are running on IIS 7.5 + .NET 4. The sites use the SSRS Report Viewer to show reports from an another server.
We recently moved both the websites and RS to new servers (switching from RS 2005 to RS 2008 and switching from IIS 7.0 to IIS 7.5). However, after moved to the new servers, one of the websites are unable to view the reporting services, as we get the following error:
request failed with HTTP status 401
The strange thing is, that the Report Viewer is configured exactly the same way in the two websites (simply copy pasted between the two). Further, using the "working website", we are able to view the reports belonging to both websites - and using the other website, we are unable to view any of the reports.
The authorization looks like this in both cases:
Credentials:
[Serializable]
public sealed class ReportServerCreditentials : IReportServerCredentials
{
public WindowsIdentity ImpersonationUser
{
get { return null; }
}
public ICredentials NetworkCredentials
{
get
{
string userName = ConfigurationManager.AppSettings["ReportViewerUser"];
string password = ConfigurationManager.AppSettings["ReportViewerPassword"];
string domain = ConfigurationManager.AppSettings["ReportViewerDomain"];
return new NetworkCredential(userName, password, domain);
}
}
public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority)
{
authCookie = null;
userName = null;
password = null;
authority = null;
return false;
}
}
Report Viewer usage
public partial class ReportServicesViewer : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
string reportingFolder = ConfigurationManager.AppSettings["ReportingFolder"];
showReport(string.Format("/{0}/{1}", reportingFolder, Request.QueryString["report"]));
}
}
private void showReport(string reportPath)
{
RevReport.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["ReportServer"]);
RevReport.ServerReport.ReportServerCredentials = new ReportServerCreditentials();
RevReport.ServerReport.ReportPath = reportPath;
}
}
In aspx:
<rsweb:ReportViewer ID="RevReport" runat="server" Height="100%" Width="100%" Font-Names="Verdana" Font-Size="8pt" ProcessingMode="Remote" ZoomMode="Percent" ZoomPercent="100"></rsweb:ReportViewer>
Other observations
At one point, we tried to monitor the traffic between the website and RS using Fiddler, but somehow the communication actually worked in this case.
However, when I tried this at a later point, Fiddler gave the following response:
[Fiddler] The socket connection to <servername> failed. <br />ErrorCode: 10061. <br />No connection could be made because the target machine actively refused it 10.0.0.17:443
I am not sure how exactly to interpret this, as we are not using SSL for the Website <-> RS communication.
Any advice would be greatly appreciated.
I had the similar issue when we built new SSRS server. Web application was not able to connect to report server. I was able to solve the issue by doing these:
Enable Kerberos Authentication on the server
Set spn(server principal names) on the server
enable the impersonation in web application

AppHarbor NopCommerce running issue

I uploaded nopcommerce solution to appharbor (using this method Can't build notcommerce project under appharbor) and solution succesfully builded, but I receiving 403 error - Forbidden: Access is denied when trying to open page(Allow write-access to file system is set to true).
Thanks and hope for your help
The problem is that the standard NopCommerce solution contains two Web Projects. AppHarbor only deploys one web project per application, and in this case, we happen to deploy Nop.Admin which is not what you want.
To resolve this, you should take advantage of the AppHarbor solution file convention and create an AppHarbor.sln solution file that only references the Nop.Web project.
We use a wrapper in our base controller to ensure that all of our code is oblivious to appharbor port changing.
First, fix in Webhelper.cs:75
public virtual string GetThisPageUrl(bool includeQueryString, bool useSsl)
{
string url = string.Empty;
if (_httpContext == null)
return url;
if (includeQueryString)
{
string storeHost = GetStoreHost(useSsl);
if (storeHost.EndsWith("/"))
storeHost = storeHost.Substring(0, storeHost.Length - 1);
url = storeHost + _httpContext.Request.RawUrl;
}
else
{
#if DEBUG
var uri = _httpContext.Request.Url;
#else
//Since appharbor changes port number due to multiple servers, we need to ensure port = 80 as in AppHarborRequesWrapper.cs
var uri = new UriBuilder
{
Scheme = _httpContext.Request.Url.Scheme,
Host = _httpContext.Request.Url.Host,
Port = 80,
Path = _httpContext.Request.Url.AbsolutePath,
Fragment = _httpContext.Request.Url.Fragment,
Query = _httpContext.Request.Url.Query.Replace("?", "")
}.Uri;
#endif
url = uri.GetLeftPart(UriPartial.Path);
}
url = url.ToLowerInvariant();
return url;
}
So what we did is simply add files from https://gist.github.com/1158264 into Nop.Core\AppHarbor
and modified base controllers:
nopcommerce\Presentation\Nop.Web\Controllers\BaseNopController.cs
public class BaseNopController : Controller
{
protected override void Initialize(RequestContext requestContext)
{
//Source: https://gist.github.com/1158264
base.Initialize(new RequestContext(new AppHarborHttpContextWrapper(System.Web.HttpContext.Current),
requestContext.RouteData));
}
//Same file from here downwards...
}
nopcommerce\Presentation\Nop.Web.Admin\Controllers\BaseNopController.cs
public class BaseNopController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
//set work context to admin mode
EngineContext.Current.Resolve<IWorkContext>().IsAdmin = true;
//Source: https://gist.github.com/1158264
base.Initialize(new RequestContext(new AppHarborHttpContextWrapper(System.Web.HttpContext.Current), requestContext.RouteData));
//base.Initialize(requestContext);
}
//Same file from here downwards...
}
Enable the Directory Browsing feature in IIS Express
Note This method is for the web developers who experience the issue when they use IIS Express.
To do this, follow these steps:
Open a command prompt, and then go to the IIS Express folder on your computer. For example, go to the following folder in a command prompt:
C:\Program Files\IIS Express
Type the following command, and then press Enter:
appcmd set config /section:directoryBrowse /enabled:true
refrence :https://support.microsoft.com/en-us/kb/942062

A local error has occurred while connecting to AD in Windows 2008 server

There's Active directory on windows 2000 advance server, I have a web server on Windows 2008 server Enterprise Edition, the following code works fine in Winsows 2003 server but when I installed Win 2008 server, it gives me the following error, the webserver is not subdomain of the AD server. but they have the same range IP address.
A local error has occurred.
System.DirectoryServices.DirectoryServicesCOMException
I want to Authenticate Via AD from my webserver, I even test the port 389 and it was open(by telnet), I even added port 389 UDP and TCP to firewall of webserver to be sure it is open, even I turned the firewall off but nothing changed. I don't know what's wrong with Windows 2008 server that cannot run my code, I search Internet but I found nothing.
any solution would be helpful.
Thank you
public bool IsAuthenticated(string username, string pwd,string group)
{
string domainAndUsername = "LDAP://192.xx.xx.xx:389/DC=test,DC=oc,DC=com" ;
string usr="CN=" + username + ",CN=" + group;
DirectoryEntry entry = new DirectoryEntry(domainAndUsername, usr, pwd,
AuthenticationTypes.Secure );
try
{
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
SearchResult result = search.FindOne();
if (result == null)
{
return false;
}
}
catch (Exception ex)
{
return false;
}
return true;
}
Ok, let's try a different approach... You indicated that you're on Windows 2008 which means that you should be able to use the new System.DirectoryServices.AccountManagement-namespace introduced in .NET 3.5.
I've written a quick function that you can try out which should work better than the code you're currently using:
using System.DirectoryServices.AccountManagement;
//...
private Boolean IsAuthenticated(String username, String password, String group)
{
PrincipalContext domain;
try
{
// Connect to the domain:
domain = new PrincipalContext(ContextType.Domain, "192.xx.xx.xx", username, password);
}
catch
{
// Unable to connect to the domain (connection error or bad username/password):
return false;
}
PrincipalSearcher searcher = new PrincipalSearcher();
// Search for the user in the domain:
UserPrincipal findUser = new UserPrincipal(domain);
findUser.SamAccountName = username;
searcher.QueryFilter = findUser;
UserPrincipal foundUser = (UserPrincipal)searcher.FindOne();
// Search for the group in the domain:
GroupPrincipal findGroup = new GroupPrincipal(domain);
findGroup.SamAccountName = group;
searcher.QueryFilter = findGroup;
GroupPrincipal foundGroup = (GroupPrincipal)searcher.FindOne();
if (foundGroup != null)
{
// Return true if group exists and the user is a member:
return foundUser.IsMemberOf(foundGroup);
}
else
{
// Group was not found:
return false;
}
}
However I would recommend that you set up a service account in your domain and use that account (with a password that you know) in your application instead of connecting to the directory with the username/password of the user that you're autenticating.
The DirectorySearcher class is most likely the culprit.
Per MSDN on DirectorySearcher:
"Windows 7, Windows Vista SP1 or later, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role not supported), Windows Server 2003 SP2
The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements. "
The error you're getting indicates that you're able to access Active Directory (not a firewall issue) but AD is unable to process the request.
I'm not sure why the code worked on Server 2003 because these two lines...
string usr="CN=" + username + ",CN=" + group;
DirectoryEntry entry = new DirectoryEntry(domainAndUsername, usr, pwd, AuthenticationTypes.Secure );
...should never work because you're not supplying the username in the correct way (you can't simply add the username to a group name, it's not a valid DN). If you change it to...
DirectoryEntry entry = new DirectoryEntry(domainAndUsername, username, pwd, AuthenticationTypes.Secure );
...you should be able to make a successful connection to AD. There won't be any check if the user belongs to the supplied group however.

Resources