Hosting WPF application within IIS - c#

I have created a WPF application (contains 8 projects).
one project is of type (Class Library) ,this dll contains class which implement
System.Web.IHttpHandler as the following.
public class ReportFileHttpHandler : IHttpHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
// some code
}
}
this HttpHandler is designed to interrupt the IIS request and handle the requrest of the xml file.
I also created a web.config file which exists inside this dll.
<system.webServer>
<handlers>
<add verb="*" path="*.xml" type="ReportFileHttpHandler" name="ReportFileHttpHandler"/>
</handlers>
Every thing is good here.
I want to do the following : I want to test the code inside the "ReportFileHttpHandler" ,so I need to host the my WPF application within (inside) the IIS to make test.
in this way I can write URL inside the Browser (which end with .xml) to execute the code in the method
public void ProcessRequrest(HttpContext context)
How can I Host the WPF application inside the IIS ?
any idea will be helpful, thank you

Create a webapplication in IIS say MyWPFApp.
Set physical path of application to directory where ReportFileHttpHandler assembly resides say C:\xxx\ReportFileHttpHandler\bin\Debug.
Make sure that ReportFileHttpHandler.dll and web.config are in same directory.
Browse url http://localhost/mywpfapp/myfile.xml in browser.
If you attach w3wp.exe process corresponding to app pool of your web application in Visual Studio, you should be able to debug your handler dll.

Related

configuration page for mvc 5 application

I'm developing an ASP.NET application using the MVC 5 framework. This application will ultimately be deployed on-premise. Therefore, users need to be able to install and configure the application before they can start using it. I need them to be able to specify things like the database name (MSSQL), the locations of various supporting services, and certain credentials like API keys for third-party services.
In a few MVC 5 applications I've used, these settings could be managed through a form. So I thought of creating a Configurations controller with GET and POST Edit actions. So the user can install the app, and then go to http://myServer/myApp/Config and specify the various settings there.
What I'm not sure about is where those settings would then be stored. Would it be the web.config file, or a settings.xml file, or the database?
Here's the strange thing... I already have a working solution with web.config that uses the below code:
public class ConfigController : Controller
{
// GET: Config/Edit/5
[HttpGet]
public ActionResult Edit()
{
ViewBag.DatabaseServer = WebConfigurationManager.AppSettings["DatabaseServer"];
ViewBag.DatabaseName = WebConfigurationManager.AppSettings["DatabaseName"];
ViewBag.PusherClientID = WebConfigurationManager.AppSettings["ClientID"];
ViewBag.PusherAPIKey = WebConfigurationManager.AppSettings["APIKey"];
return View();
}
// POST: Config/Edit/5
[HttpPost]
public ActionResult Edit(FormCollection collection)
{
WebConfigurationManager.AppSettings.Set("DatabaseServer", collection.Get("databaseserver"));
WebConfigurationManager.AppSettings.Set("DatabaseName", collection.Get("databasename"));
WebConfigurationManager.AppSettings.Set("ClientID", collection.Get("pusherclientid"));
WebConfigurationManager.AppSettings.Set("APIKey", collection.Get("pusherapikey"));
return RedirectToAction("Edit");
}
}
And my web.config file:
<appSettings>
...
<add key="DatabaseServer" value="localhost\sqlexpress" />
<add key="DatabaseName" value="MyDatabase" />
<add key="ClientID" value="testID" />
<add key="APIKey" value="testkey" />
</appSettings>
I can change these variables on a form on edit.cshtml and they persist fine. Two problems:
I can't figure out where they go. I'm told they go in web.config but I checked both web.config files inside my app and none of them have the updated values. On the form, I update ClientID to "123" but in web.config it still says "testID" which is the original default value.
I'm told that updating web.config will cause the app pool to restart. Yet that doesn't seem to be the case here...
Can someone explain what is going on?
You are missing,
WebConfigurationManager.Save();
in your post to edit.
The changes you are making are only being applied at run time. The reason you are not causing the app pool to restart is because you have not committed your changes.
Here is a reference I found: modify the web config at run-time
Do Note that in the long run as stated in the referenced link you should not store settings that are edited frequently in your web config. Use an XML or json file to store those settings and load them as needed.
Unless you call the Save method on the configuration, It won't be persisted to the physical file(Web.config). That means, you will still be able to read the app setting entry values you set until the app pool recycles. But if your app pool recycle/IIS get restarted, you will loose whatever you set to the AppSettings.
Save method writes the config settings to the current XML configuration file.
Keep in mind that, the user or process that writes config file entries must have the following permissions:
Write permission on the configuration file and directory at the current configuration hierarchy level.
Read permissions on all the configuration files.
If you really want to persist the app settings entries to the files, you can do this
[HttpPost]
public ActionResult Edit(FormCollection collection)
{
var config = WebConfigurationManager.OpenWebConfiguration("~");
var db = config.AppSettings.Settings["DatabaseServerName"];
if (db != null)
{
config.AppSettings.Settings["DatabaseServerName"].Value = id;
}
else
{
var dbEntry=new KeyValueConfigurationElement("DatabaseServerName",id);
config.AppSettings.Settings.Add(dbEntry);
}
config.Save();
// to do : Redirect to a success action (PRG pattern)
}
In your case, to set the db server name & api keys, you should be calling the Save method so that they are persisted in the file and will be available later even after the app pool restarts.

Unable to update ServiceReference or add again after deleting?

I have a web app project and silverlight project in the solution. I have WCF file in web app, and I get the below error while updating the ServiceReference
There was an error downloading 'http://localhost:5678/DataForSilverlight.svc/_vti_bin/ListData.svc/$metadata'.
The request failed with HTTP status 404: Not Found.
Metadata contains a reference that cannot be resolved: 'http://localhost:5678/DataForSilverlight.svc'.
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
If the service is defined in the current solution, try building the solution and adding the service reference again.
I also tried to Delete it and add it again, and I also tried deleting WCF file from web application.
This error usually happens when you're exposing the web application (and then your WCF service) through IIS, using a dynamic port, that changes every time you start and stop the debugging of the solution.
To avoid this problem, right click on the Web project and select 'Properties'. Select the tab 'Web'. In the groupbox named 'Servers', insert your desired network path and click the button 'Create Virtual Directory'. IIS will create a virtual directory for your web project.
Now you can add your service reference to the Silverlight project. The next time you execute the web project, the IIS will execute the web application using the desired network path.
Also, make sure that in the class definition of your service the following attributes are declared:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DataForSilverlight
and that the following line is existing in your Web.Config file, in <system.serviceModel> section:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
Dont know why but i again changed the variable type in the Method which was befor change is
[OperationContract]
void SaveData(int UserId, string FileName, ExtendedImage File);
later changed it to string
[OperationContract]
void SaveData(int UserId, string FileName, string File);
and everything works fine now

Registering HttpHandler for IIS 7.0

Very simple question, but nonetheless confusing. According to the Microsoft documentation, it is necessary to register a HttpHandler (used to serve images dynamically from DB) in the <handlers> section of the Web.Config file:
How to: Register HTTP Handlers
This was also specified in a previous answer on this topic:
HttpHandler not Working in IIS 7
The confusion stems from the fact that I currently have it working in an ASP.NET Web Forms project without any entry in the config file. Can someone shed some light on this and if it may effect the performance of the handler for this particular task?
public class ImageHandler : IHttpHandler
{
....
}
It wasn't entirely clear in your question, but in the comments we have established that you are asking why a handler that's exposed via an ASP.NET .ashx file does not need to be mapped. The answer is simple: when ASP.NET is installed it adds a global handler to IIS7 for the *.ashx extension with the name SimplerHandlerFactory-Integrated and SimpleHandlerFactory-Integrated-4.0. This handler simply acts like a wrapper and executes the underlying IHttpHandler implementation that is pointed to by the ASHX.

Deploying an HttpHandler web service

I am trying to build a webservice that manipulates http requests POST and GET.
Here is a sample:
public class CodebookHttpHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.Request.HttpMethod == "POST")
{
//DoHttpPostLogic();
}
else if (context.Request.HttpMethod == "GET")
{
//DoHttpGetLogic();
}
}
...
public void DoHttpPostLogic()
{
...
}
public void DoHttpGetLogic()
{
...
}
I need to deploy this but I am struggling how to start. Most online references show making a website, but really, all I want to do is respond when an HttpPost is sent. I don't know what to put in the website, just want that code to run.
Edit:
I am following this site as its exactly what I'm trying to do.
I have the website set up, I have the code for the handler in a .cs file, i have edited the web.config to add the handler for the file extension I need. Now I am at the step 3 where you tell IIS about this extension and map it to ASP.NET. Also I am using IIS 7 so interface is slightly different than the screenshots. This is the problem I have:
1) Go to website
2) Go to handler mappings
3) Go Add Script Map
4) request path - put the extension I want to handle
5) Executable- it seems i am told to set aspnet_isapi.dll here. Maybe this is incorrect?
6) Give name
7) Hit OK button:
Add Script Map
Do you want to allow this ISAPI extension? Click "Yes" to add the extension with an "Allowed" entry to the ISAPI and CGI Restrictions list or to update an existing extension entry to "Allowed" in the ISAPI and CGI Restrictions list.
Yes No Cancel
8) Hit Yes
Add Script Map
The specified module required by this handler is not in the modules list. If you are adding a script map handler mapping, the IsapiModule or the CgiModule must be in the modules list.
OK
edit 2: Have just figured out that that managed handler had something to do with handlers witten in managed code, script map was to help configuring an executable and module mapping to work with http Modules. So I should be using option 1 - Add Managed Handler.
I know what my request path is for the file extension... and I know name (can call it whatever I like), so it must be the Type field I am struggling with. In the applications folder (in IIS) so far I just have the MyHandler.cs and web.config (Of course also a file with the extension I am trying to create the handler for!)
edit3: progress
So now I have the code and the web.config set up I test to see If I can browse to the filename.CustomExtension file:
HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.
So in IIS7 I go to Handler Mappings and add it in. See this MSDN example, it is exactly what I am trying to follow
The class looks like this:
using System.Web;
namespace HandlerAttempt2
{
public class MyHandler : IHttpHandler
{
public MyHandler()
{
//TODO: Add constructor logic here
}
public void ProcessRequest(HttpContext context)
{
var objResponse = context.Response;
objResponse.Write("<html><body><h1>It just worked");
objResponse.Write("</body></html>");
}
public bool IsReusable
{
get
{
return true;
}
}
}
}
I add the Handler in as follows:
Request path: *.whatever
Type: MyHandler (class name - this appears correct as per example!)
Name: whatever
Try to browse to the custom file again (this is in app pool as Integrated):
HTTP Error 500.21 - Internal Server Error
Handler "whatever" has a bad module "ManagedPipelineHandler" in its module list
Try to browse to the custom file again (this is in app pool as CLASSIC):
HTTP Error 404.17 - Not Found
The requested content appears to be script and will not be served by the static file handler.
Direct Questions
1) Does the website need to be in CLASSIC or INTEGRATED mode? I don't find any reference of this in the online material, whether it should be either.
2) Do I have to compile the MyHandler.cs to a .dll, or can I just leave it as .cs? Does it need to be in a bin folder, or just anywhere in root?
RE your questions:
I don't know the answer to the first one (CLASSIC or INTEGRATED); but I can help with the second...
Yes you'll need to compile it first. I have never tried deploying dll's to anywhere other than the bin, given that that's the standard I would be suspect in putting them anywhere else even if it did work.
The way I deploy HttpHandlers is quiet straight forward - all the hard work's done in web.config, I'v enever had to go into IIS to change any settings.
For a start, for the http request to be handled by ASP.NET you need to use a request suffix that's already piped to ASP.NET - like .aspx or ashx. If you want to use something else you will need to config IIS to do this, as per your managed handler img above.
I tend to use .ashx e.g: http://localhost/foo/my/httphandler/does/this.ashx
All you need to do (assuming you've compiled athe HttpHandler into a DLL and deployed it to the site) is add the necessary config.
<configuration>
<system.web>
<httpHandlers>
<add verb="*"
path="*.ashx"
type="MyApp.PublishingSystem.HttpHandlers.GroovyHandler, MyApp.PublishingSystem" />
</httpHandlers>
</system.web>
</configuration>
Obviously (?) you can change / restrict the scope using the path, e.g:
path="*.ashx"
path="*ListWidgets.ashx"
path="*Admin/ListWidgets.ashx"
More info here: http://msdn.microsoft.com/en-us/library/ms820032.aspx
An important gotcha to look out for is the order in which you declare your HttpHandlers in the config; from what I remember ones declared first take precedent. So in this example...
<add verb="*" path="*foo.ashx" type="MyApp.PublishingSystem.HttpHandlers.FooHandler, MyApp.PublishingSystem" />
<add verb="*" path="*.ashx" type="MyApp.PublishingSystem.HttpHandlers.GroovyHandler, MyApp.PublishingSystem" />
...the groovy handler will handle all HttpRequests except any that end in foo.ashx
By the way, I make use of HttpHanldrs in my open source .net CMS / app framework, you might find some helpful code there (?): http://morphfolia.codeplex.com/
Make sure the app pool's .NET Framework Version is set correctly...
I deployed a .NET 4.0 web app on a .NET 2.0 app pool and got this error. Set the app pool to v4.X and the ashx was served like a champ.

Why CSS files not loading when compressing HTTP response using GZipStream?

I am developing an application using asp.net 2.0 (C#), in which I am trying to implement the compression of my files, so that performance of my website will improve.
For that I have added a code in my Global.asax file to compress all requests (.aspx, .js, .css) But when I am running my application it works well for first time then the CSS is not loading and web page is not rendering properly.
Why its happening??
Edited (added my compression code)
My compression code of Global.asax file is as follows:
void Application_BeginRequest()
{
HttpContext incoming = HttpContext.Current;
string oldpath = incoming.Request.Path.ToLower();
incoming.Response.Filter = new GZipStream(incoming.Response.Filter, CompressionMode.Compress);
HttpContext.Current.Response.AppendHeader("Content-encoding", "gzip");
HttpContext.Current.Response.Cache.VaryByHeaders["Accept-encoding"] = true;
}
Also please let me know if there is any other better way to do the same, using the Global.asax file, because I don't have access of IIS Settings and also I don't have permission to implement the HttpModule, that is why I am using Global.asax file.
Thanks
For static files, you can configure IIS to do the compression for you, no need to implement it yourself.
In IIS6 this is a global setting (properties of the "Web Sites" node in IIS manager, service tab).
In IIS7 this is set on a per folder basis, and it will also compress dynamic content for you. It can either be set in IIS Manager or in the web.config file:
<configuration>
<system.webServer>
<urlCompression doDynamicCompression="true" doStaticCompression="true" />
</system.webServer>
</configuration>

Categories