using ISA to expose an internal MVC website - asp.net-mvc-3

We have an internal server running an MVC3 application, which has been made available on our external server by using an ISA server.
However; it is not applying the CSS, as the references to the external site are not mapped correctly.
The main difference between the 2, that I can see, is internally it runs as an application on the internal server (http://InternalServer/MVCSite)
The External Server is seen as running as an application within a subsite (http://ExternalDomain/SubSite/MVCSite), this is what the world gets.
looking at the source the URL generated I can see that is behaves like the internal site, returning: #Url.Content("~/Content/Site.css") as /MVCSite/Content/Site.css.
And I have been looking at this article to see if it sheds any light: http://support.microsoft.com/kb/885186
I have thought that it might be that the redirection cannot handle differences in site structures? So, modifying the internal site to reflect the external layout will fix any uses. Internally InternalServer/MVCSite becomes ExternalDomain/SubSite/MVCSite
I will add more as I find things out.

This answer is not related to isa, and there is probably a proper way to do this configuring it. However if you cannot find the right solution, HttpRuntime.AppDomainAppVirtualPath may help you.
Instead of using: #Url.Content("~/Content/Site.css"), you can try #Url.Content(HttpRuntime.AppDomainAppVirtualPath + "Content/Site.css")
If this doesn't work, you can override the value of AppDomainAppVirtualPath using reflection. Have a look here: http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_24475811.html#a24591595.
Dim vpathTypeName As String = "System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Dim virtualPath As Object = ReflectionHelper.Instantiate(vpathTypeName, New Type() {GetType(String)}, New Object() {"/"})
ReflectionHelper.SetPrivateInstanceFieldValue("_appDomainAppVPath", runtime, virtualPath)
It basically updates an static field with whatever value you need. You can validate the host header with : HttpContext.Current.Request.Url.Host and set the value to / or /SubSite/

Related

How does a HTTP endpoint/URI relate to the WebAPI that it calls

this is a simple question, but for one new to deploying web-based applications its (at least to me) pretty fundamental but not explicitly clear in any of the examples that I have picked up from the web (they all seem to assume a certian level of knowledge). I have a WebAPI service (as per the VS Project called PiHttpTransferService), this has an apicontroller:
Namespace Controllers
Public Class PIInterfaceController
Inherits ApiController
<Route("{forThisTime}/{piServerName}/{piPntSrc}/{piTagFilter}")>
<HttpGet>
Public Function GetPiData(ByVal forThisTime As DateTime, ByVal piServerName As String, ByVal piPntSrc As String, ByVal piTagFilter As String) As String
Dim result As String = Nothing
'Code to do get data from a database
Return result
End Function
End Class
End Namespace
How does this relate to requests made from a web browser. Apologies for a question that I am sure is pretty basic knowledge to most on here, but the starting height for my bar is pretty low :-)
Kind Regards
Paul.
Generally you deploy your API to a server somewhere, which makes it available at a particular address/ URL.
In IIS this is a website, which will have bindings associated with it, and those bindings will have details of things like the hostname or IP address and ports which that website should response to. e.g. https://www.example.com
When you run/ debug your project in Visual Studio, it takes care of this for you and starts a cut-down webserver that points to your compiled code with a binding for your project that has a random port number associated with it. This is why you see things like http://localhost:7812 in your browser.
The routes which you define on your controller methods are the paths which should be appended to the hostname to target that particular method. So from your controller above, you would access the method with a call similar to this (hostnames for example only, obviously :P ):
https://www.example.com/2020-01-01T00:00:00Z/servername/1/tag/
http://localhost:7812/2020-01-01T00:00:00Z/servername/1/tag/
This is brief, and hopefully helpful, but there are a lot of things that could be discussed here such as configuring bindings or DNS or maybe even app pools. I hope this gets to the initial crux of your question though.

How to access web.config sections in a Web service called from another application?

I'm working on a Web service with Visual Studio, framework 4.7.1. One of its Web methods needs to call another Web service (provided by another company). It converts the parameters it receives (that are consistent with our main application's business logic) into values the other Web service can handle (according to it's own business logic). To do this, it relies heavily on data stored in the Web.config file.
I tested it directly (start the Web service and call the Web methods with automatically generated pages on a Web browser page) and everything worked fine.
Now, I need to build a test application (also in Visual Studio, framework 4.7.1) to call the same Web methods. On first testing it, I noticed that the Web service was trying to access the test application's config file instead of its own (as described in Can't read Web.config with ConfigurationManager.AppSettings ).
So I created an applicationSettings section in the Web.config and moved all the data from appSettings into it. It worked fine.
Now, however, I notice that the same thing happens with the custom sections. One of them looks like this:
<configSections>
<section name="jobTypeLists" type="AdelSoft_WS_FRA.JobTypesSection" />
</configSections>
<jobTypeLists>
<jobTypes>
<jobType codeCustomerType="A" codeJobType="JobForA" />
<jobType codeCustomerType="B" codeJobType="JobForB" />
</jobTypes>
</jobTypeLists>
I can see how such a structure could fit into its own .settings file, but I have another one that is much more complicated. (Like, the text nodes can have up to four ancestors.) To keep this short-ish, I'm not providing it now, but it can easily be arranged.
ConfigurationManager.GetSection("jobTypeLists") returns null when called from the test application. Same with WebConfigurationManager.GetSection("jobTypeLists").
I've also tried accessing the configuration file with ConfigurationManager.OpenExeConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), but I can't seem to find my sections in the Configuration object it returns.
I'm not sure it means anything, but the Configuration object's FilePath property contains "C:\Folder\InnerFolder\WebServiceFolder\web.config.config". Why this second ".config"? I tried passing the same string to ConfigurationManager.OpenExeConfiguration(), without the ".config" extension: it returned null. (As it should, I feel.)
The Configuration object has 10 section groups and 22 sections, which I can't make heads or tails from. Likewise, I can list them.
Actually, there are two ways for a Visual Studio project to reference a Web service: as a regular reference (like you would any other project) or as a Web reference.
I was using the former, and therein lay my mistake.
To reference the Web service, I started it, copied the URL from the browser window that it opened, and pasted it into the "URL" text box in the "Add a Web reference" window from my test application. From there on, it worked fine.
(By the way, I have kept the regular reference as well, because I'm using some constants from the Web service to handle return values.)

asp.net-web-api using culture for returning errors in different languages

I'm using ASP.NET Web API 2,
I have resx files for errors, I need to return the error in the correct language (by user culture).
My solution is
1)I created BaseApiController that all the other controllers would inherit.
2)In BaseApiController I changed the Thread.CurrentThread.CurrentCulture for each request.
My question is if this is the correct way for doing it?
Thanks a lot!
There are lots of way doing this. It actually depends on your architecture. Your way is also acceptable. You will implement ResourceManager if you use your way. Let me give some other examples:
You can keep language code in request header and you don't need to
change Thread.CurrentThread.CurrentCulture.
You can store errors in database with language code and you can get
corresponding error with the active culture when the operation is
failed.
You can store errors in cache with language code and you can get
corresponding error with the active culture when the operation is
failed.
As you can see, there are lots of ways. As I said it depends on your architecture.
Good luck

ProtocolViolationException Load testing web service (GET action with content-body)

I created an ASP.NET MVC4 Web API service (REST) with a single GET action. The action currently needs 11 input values, so rather than passing all of those values in the URL, I opted to encapsulate those values into a single class type and have it passed as Content-Body. When I test in Fiddler, I specify the verb as GET, and enter the JSON text in the "Request Body" input box. This works great!
The problem is when I attempt to perform Load Testing in Visual Studio 2010 Ultimate. I am able to specify the GET action and the JSON Content-Body just fine. But when I run the Load test, VS reports exceptions of type ProtocolViolationException (Cannot send a content-body with this verb-type) in the test results. The test executes in 1ms so I suspect the exceptions are causing the test to immediately abort. What can I do to avoid those exceptions? I'd prefer to not change my API to use URL arguments just to work-around the test tooling. If I should change the API for other reasons, let me know. Thanks!
I found it easier to put this answer rather than carry on the discussions.
Sending content with GET is not defined in RFC 2616 yet it has not been prohibited. So as far as the spec is concerned we are in a territory that we have to make our judgement.
GET is canonically used to get a resource. So you are retrieving this resource using this verb with the parameters you are sending. Since GET is both safe and idempotent, it is ideal for caching. Caching usually takes place based on the resource URI - and sometimes based on various headers. The point is cache implementations - AFAIK - would not use the GET content (and to be honest I have not seen any GET with content in real world). And it would not make sense to include the content in the key generation since it reduces the scalability of the caches.
If you have parameters to send, they must be in the URI since this is part of what defines that URI. As such, I strongly believe sending content with GET is wrong.
Even when you look at implementations such as OData, they put the criteria in the URI. I cannot imagine your (or any) applications requirements is beyond OData query requirements.

ASP.NET MVC 3: Purpose of IgnoreRoute("{resource}.axd/{*pathInfo}"); ? deprecated?

Do I even need this rule anymore?
I don't see any requests incoming for resource.axd files (as opposed to when I ran webform applications)
WebResource.axd is an HTTP Handler that is part of the .NET Framework
that does one thing and one thing only – it is tasked with getting an
embedded resource out of a DLL and returning its content. What DLL to
go to and what embedded resource to take are specified through the
querystring. For instance, a request to
www.yoursite.com/WebResource.axd?d=EqSMS…&t=63421… might return a
particular snippet of JavaScript embedded in a particular assembly.
Its still part of the framework and you can still retrieve embedded resources using the above handler. You dont want your route handler to handle such requests and that is why it is ignored. My guess is that you can get rid of it if you are completely sure that your app/libraries that you use dont use it.

Resources