Recently, I was working on an AJAX UpdatePanel with multiple triggers. I noticed I received the following JavaScript error in IE7, but not FireFox:
'Sys.InvalidOperationException: Could not find UpdatePanel with ID 'xxx'. If it is being updated dynamically then it must be inside another UpdatePanel.'
My page was written as follows (with each trigger on its own line (to make it readable)):
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate></ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnImg1" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnImg2" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnImg3" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnImg4" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
I had read that adding the UpdateMode=Conditional and adding an specific EventName to each trigger would maybe resolve my problem, however, it did not, but I left it in just in case.
I had only noticed this problem in IE after I had added the fourth trigger. I also noticed if I removed the fourth trigger, there was no JavaScript error. So I then change my page to the following (put all the triggers on a single line):
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate></ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnImg1" EventName="Click" /><asp:AsyncPostBackTrigger ControlID="btnImg2" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="btnImg3" EventName="Click" /><asp:AsyncPostBackTrigger ControlID="btnImg4" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
This seemed to fix the problem, even moving it to two lines worked. So I guess it was a whitespace issue? Very strange...only in IE!
*note my content template it blank because I'm actually working with a swfobject to play a movie...so there is a lot more code here but I'm only showing the specific area that was broken...
Tuesday, December 14, 2010
Monday, November 22, 2010
Deleted SSL Certificate Request - Recreate Request
After importing a new certificate, I deleted it because the friendly name was blank. (little did I know that was a known error with a simple fix.) However, I figured I had done something wrong when I installed so I deleted the certificate, which left me with no pending certificate request to complete the install again.
So now, I had to either contact the CA and re-process the request, or somehow get my pending request back. I went for 'get my pending request back'.
After googling for this info, I was able to find some help on this. So these are the steps I did to accomplish this. (Windows 2008 Server/IIS 7)
1. Click Start, point to Run, type cmd, and then click OK.
2. Navigate to the directory where Certutil.exe is stored; by default, this is %windir%\system32.
3. Type the following command at the command prompt: certutil -addstore my "C:\junk\www_sitename_com.cer" *a little note "my" is a part of the command, at first i thought it was part of an example name.
You should see the following message somewhere in the message that follows: CertUtil: -addstore command completed successfully.
4. Get the Thumbprint of the certificate.
5. Start- type 'mmc'. File - Add/Remove Snapin. Add Certificates, Select Local Computer.
6. Next, go to: Certificates - Certificate Enrollment Requests - Certificate. Double-click the certificate.
7. Go to the Details tab, scroll down, copy the weird thumbprint value, paste into Notepad for reference.
8. Return to the Command prompt, type the following command: certutil -repairstore my "xx dd xx xx oo" (include your own thumbprint value in double quotes.)
Go back to the IIS and follow the steps to Complete Certificate request.
And, btw, don't forget to go back to the IIS manager, and select the new certificate for the SSL/HTTPS binding
for the site.
So now, I had to either contact the CA and re-process the request, or somehow get my pending request back. I went for 'get my pending request back'.
After googling for this info, I was able to find some help on this. So these are the steps I did to accomplish this. (Windows 2008 Server/IIS 7)
1. Click Start, point to Run, type cmd, and then click OK.
2. Navigate to the directory where Certutil.exe is stored; by default, this is %windir%\system32.
3. Type the following command at the command prompt: certutil -addstore my "C:\junk\www_sitename_com.cer" *a little note "my" is a part of the command, at first i thought it was part of an example name.
You should see the following message somewhere in the message that follows: CertUtil: -addstore command completed successfully.
4. Get the Thumbprint of the certificate.
5. Start- type 'mmc'. File - Add/Remove Snapin. Add Certificates, Select Local Computer.
6. Next, go to: Certificates - Certificate Enrollment Requests - Certificate. Double-click the certificate.
7. Go to the Details tab, scroll down, copy the weird thumbprint value, paste into Notepad for reference.
8. Return to the Command prompt, type the following command: certutil -repairstore my "xx dd xx xx oo" (include your own thumbprint value in double quotes.)
Go back to the IIS and follow the steps to Complete Certificate request.
And, btw, don't forget to go back to the IIS manager, and select the new certificate for the SSL/HTTPS binding
for the site.
Monday, November 15, 2010
IIS 7 Secure Files Type like .txt or .html
I've had an .Net 2.0/IIS 4 site running for a long time that was to provide access to documents, but the documents were to be categorized and secured. I did my best to obscure the file structure and document names and not allow bot files in. But I was never quite satisfied with this because you could not fully secure the files such as .doc, or .txt. There was potential to serve up these pages, very annoying.
My understanding of the IIS 7.0/4.0 Integrated Pipeline is that you can secure files other than .aspx. I started using IIS 7 months ago, but never really understood what this new integrated pipeline could do for me until recently. I had to dig to even figure this out on my own. sigh...
Anyhow, by putting your site in 4.0 Integrated Pipeline mode and adding a few configuration lines to a "Form secured site", you can now require security on those "other" file types. Yes, just what i needed!
It was pretty simple, and I am hoping I'm right on with my understanding. If I'm wrong please let me know!!
I just modified the Application Pool to use 4.0 Integrated Mode. Then added the following lines to the web.config, inside the system.webserver tag:
<modules>
<remove name="FormsAuthenticationModule" />
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
My understanding of the IIS 7.0/4.0 Integrated Pipeline is that you can secure files other than .aspx. I started using IIS 7 months ago, but never really understood what this new integrated pipeline could do for me until recently. I had to dig to even figure this out on my own. sigh...
Anyhow, by putting your site in 4.0 Integrated Pipeline mode and adding a few configuration lines to a "Form secured site", you can now require security on those "other" file types. Yes, just what i needed!
It was pretty simple, and I am hoping I'm right on with my understanding. If I'm wrong please let me know!!
I just modified the Application Pool to use 4.0 Integrated Mode. Then added the following lines to the web.config, inside the system.webserver tag:
<modules>
<remove name="FormsAuthenticationModule" />
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
Thursday, September 16, 2010
Tips: FedEx WebService for Rate Quotes C#/Asp.Net
After a long run of using the UPS quotes for online orders, we moved to FedEx. So that meant, I needed to update the ecommerce app to reflect our new shipper.
This task wasn't *too* hard since I had already written the UPS one about 4 years ago, but the FedEx one uses a WebService, for the UPS rates, I sent an HttpWebRequest. I don't know why they don't have webservice, maybe they do now...
Anyhow, hopefully these tips will help get you started on your way.
1. Get the WSDL. To do this, I downloaded the WSDL file from FedEx, this file includes the RateService_v9.wsdl file. I unzipped this file to my local webserver, then to my production webserver.
2. Create a reference to the WebService in Visual Studio. In my project, I right-clicked then selected Add Web Reference. Then I pointed the reference to my localhost (http://localhost/fedex/RateService_v9.wsdl) and gave it a name.
3. Requested a Test Key from FedEx that I plugged into the values Account Number, Meter Number, Key and Password.
4. Downloaded the FedEx example for getting Rate Service Quotes. Modified it to my liking. Here's a snippet:
RateRequest request = new RateRequest();
RateService service = new RateService(); // Initialize the service
request.WebAuthenticationDetail = new WebAuthenticationDetail();
request.WebAuthenticationDetail.UserCredential = new WebAuthenticationCredential();
request.WebAuthenticationDetail.UserCredential.Key = this._key; // Replace "XXX" with the Key
request.WebAuthenticationDetail.UserCredential.Password = this._password; // Replace "XXX" with the Password
//
request.ClientDetail = new ClientDetail();
request.ClientDetail.AccountNumber = this._accountNumber; // account number
request.ClientDetail.MeterNumber = this._meter; // meter number
//
request.TransactionDetail = new TransactionDetail();
request.TransactionDetail.CustomerTransactionId = "MY-RATE-REQUEST";
//
request.Version = new VersionId(); // automatically set from wsdl
if (packages != null && packages.Count > 0)
{
SetShipmentDetails(request, packages.Count);
int i = 0;
decimal totalWeight = 0.0M;
foreach (Package package in packages){
RequestedPackageLineItem rpli = new RequestedPackageLineItem();
Weight packageWeight = new Weight();
packageWeight.Value = (decimal)package.Weight;
packageWeight.Units = WeightUnits.LB;
rpli.Weight = packageWeight;
totalWeight += (decimal)package.Weight;
request.RequestedShipment.RequestedPackageLineItems[i] = rpli;
i++;
}
Weight weight = new Weight();
weight.Value = totalWeight;
weight.Units = WeightUnits.LB;
request.RequestedShipment.TotalWeight = weight;
}
.....
5. Once I was satisfied with the results, I requested a Production Key from FedEx then plugged in those values. I kept receiving a "Meter Number is missing or invalid".
This where I got tripped up. I had to change the URL being called in the app.config (that seems to have been created for me with properties in it). There is a url value that is referenced by the WebService.
However, even though I kept changing this value, it would continue to use the old value which was the test site, and of course, give me the same error - since my meter number was a production one not a test one.
Finally, I thought to open up the Properties - Settings.settings file. Right when I double-clicked the file to open it, the proprety inside there was updated with the new value I had in the app.config file.
I assume it was some sort of Visual Studio 2010 thing. It seems like it was supposed to auto-update but it didn't. Later, to be sure, I just updated it manually.
After that everything worked like a charm.
FYI:
(for SOAP Requests)
The test url is: https://wsbeta.fedex.com:443/web-services/rate
The production url is: https://gateway.fedex.com:443/web-services
This task wasn't *too* hard since I had already written the UPS one about 4 years ago, but the FedEx one uses a WebService, for the UPS rates, I sent an HttpWebRequest. I don't know why they don't have webservice, maybe they do now...
Anyhow, hopefully these tips will help get you started on your way.
1. Get the WSDL. To do this, I downloaded the WSDL file from FedEx, this file includes the RateService_v9.wsdl file. I unzipped this file to my local webserver, then to my production webserver.
2. Create a reference to the WebService in Visual Studio. In my project, I right-clicked then selected Add Web Reference. Then I pointed the reference to my localhost (http://localhost/fedex/RateService_v9.wsdl) and gave it a name.
3. Requested a Test Key from FedEx that I plugged into the values Account Number, Meter Number, Key and Password.
4. Downloaded the FedEx example for getting Rate Service Quotes. Modified it to my liking. Here's a snippet:
RateRequest request = new RateRequest();
RateService service = new RateService(); // Initialize the service
request.WebAuthenticationDetail = new WebAuthenticationDetail();
request.WebAuthenticationDetail.UserCredential = new WebAuthenticationCredential();
request.WebAuthenticationDetail.UserCredential.Key = this._key; // Replace "XXX" with the Key
request.WebAuthenticationDetail.UserCredential.Password = this._password; // Replace "XXX" with the Password
//
request.ClientDetail = new ClientDetail();
request.ClientDetail.AccountNumber = this._accountNumber; // account number
request.ClientDetail.MeterNumber = this._meter; // meter number
//
request.TransactionDetail = new TransactionDetail();
request.TransactionDetail.CustomerTransactionId = "MY-RATE-REQUEST";
//
request.Version = new VersionId(); // automatically set from wsdl
if (packages != null && packages.Count > 0)
{
SetShipmentDetails(request, packages.Count);
int i = 0;
decimal totalWeight = 0.0M;
foreach (Package package in packages){
RequestedPackageLineItem rpli = new RequestedPackageLineItem();
Weight packageWeight = new Weight();
packageWeight.Value = (decimal)package.Weight;
packageWeight.Units = WeightUnits.LB;
rpli.Weight = packageWeight;
totalWeight += (decimal)package.Weight;
request.RequestedShipment.RequestedPackageLineItems[i] = rpli;
i++;
}
Weight weight = new Weight();
weight.Value = totalWeight;
weight.Units = WeightUnits.LB;
request.RequestedShipment.TotalWeight = weight;
}
.....
5. Once I was satisfied with the results, I requested a Production Key from FedEx then plugged in those values. I kept receiving a "Meter Number is missing or invalid".
This where I got tripped up. I had to change the URL being called in the app.config (that seems to have been created for me with properties in it). There is a url value that is referenced by the WebService.
However, even though I kept changing this value, it would continue to use the old value which was the test site, and of course, give me the same error - since my meter number was a production one not a test one.
Finally, I thought to open up the Properties - Settings.settings file. Right when I double-clicked the file to open it, the proprety inside there was updated with the new value I had in the app.config file.
I assume it was some sort of Visual Studio 2010 thing. It seems like it was supposed to auto-update but it didn't. Later, to be sure, I just updated it manually.
After that everything worked like a charm.
FYI:
(for SOAP Requests)
The test url is: https://wsbeta.fedex.com:443/web-services/rate
The production url is: https://gateway.fedex.com:443/web-services
Labels:
Asp.Net,
C#,
FedEx WebService,
FedEx WSDL,
Rates Available
Wednesday, August 11, 2010
Active Reports Dynamic Header Label and Column Creation
For this task, I needed to modify an existing report to allow for dynamic headers and columns. I was able to accomplish this in the report_DataInitialize, although I believe I read the Report Start is the recommended place. When I tried using that, I found that I did not have the data I needed to calculate how many label and columns I would need. So far report_DataInitialize has worked just fine...keeping my fingers crossed.
This is a subreport by the way. Previously, I had the header labels in the parent report, so I did also have to add a group header to make this work right.
So pretty much, I create as many new text boxes I need for the report in a loop, making each have a unique id, and allow some spacing in between. Then I add the text box to the detail section at the defined point that has been 'calculated'.
For the header, I do the same, but create labels, and then add them to the group header.
I also populate the columns with data in the report_FetchData, using the same looping logic to find the text box name and then give it a value to display.
For the most part this wasn't too bad of a task. I took a little digging about but I think it works.
private void report_DataInitialize(object sender, System.EventArgs e)
{
if (this.Classroom.Books.Count > 0)
{
float i = 0.0F;
foreach (Book book in Classroom.Books)
{
bool isActive = book.Active ?? false;
if (isActive){
StringBuilder sb = new StringBuilder("bk_");
sb.Append(book.ID);
string fieldName = sb.ToString();
this.Fields.Add(fieldName);
TextBox tb = new TextBox();
tb.Name = fieldName;
tb.DataField = fieldName;
tb.Height = .2F;
tb.Width = 1.1F;
tb.Alignment = TextAlignment.Right;
i = (i == 0.0F) ? 1.6F : i + 1.1F;
this.Sections["detail"].Controls.Add(tb);
this.Sections["detail"].Controls[tb.Name].Location = new PointF(i, 0);
Label lbl = new Label();
lbl.Name = fieldName + "lbl";
lbl.Text = gp.Description;
lbl.Height = .2F;
lbl.Width = 1.1F;
lbl.Alignment = TextAlignment.Right;
this.Sections["groupHeader1"].Controls.Add(lbl);
this.Sections["groupHeader1"].Controls[lbl.Name].Location = new PointF(i, 0);
}
}
}
}
This is a subreport by the way. Previously, I had the header labels in the parent report, so I did also have to add a group header to make this work right.
So pretty much, I create as many new text boxes I need for the report in a loop, making each have a unique id, and allow some spacing in between. Then I add the text box to the detail section at the defined point that has been 'calculated'.
For the header, I do the same, but create labels, and then add them to the group header.
I also populate the columns with data in the report_FetchData, using the same looping logic to find the text box name and then give it a value to display.
For the most part this wasn't too bad of a task. I took a little digging about but I think it works.
private void report_DataInitialize(object sender, System.EventArgs e)
{
if (this.Classroom.Books.Count > 0)
{
float i = 0.0F;
foreach (Book book in Classroom.Books)
{
bool isActive = book.Active ?? false;
if (isActive){
StringBuilder sb = new StringBuilder("bk_");
sb.Append(book.ID);
string fieldName = sb.ToString();
this.Fields.Add(fieldName);
TextBox tb = new TextBox();
tb.Name = fieldName;
tb.DataField = fieldName;
tb.Height = .2F;
tb.Width = 1.1F;
tb.Alignment = TextAlignment.Right;
i = (i == 0.0F) ? 1.6F : i + 1.1F;
this.Sections["detail"].Controls.Add(tb);
this.Sections["detail"].Controls[tb.Name].Location = new PointF(i, 0);
Label lbl = new Label();
lbl.Name = fieldName + "lbl";
lbl.Text = gp.Description;
lbl.Height = .2F;
lbl.Width = 1.1F;
lbl.Alignment = TextAlignment.Right;
this.Sections["groupHeader1"].Controls.Add(lbl);
this.Sections["groupHeader1"].Controls[lbl.Name].Location = new PointF(i, 0);
}
}
}
}
Saturday, June 5, 2010
T-Mobile Hot Spot - Blue Phone Light Indicator
We have T-Mobile's hot spot at home for our phone line. It works fine most of the time, however, when there is a storm and the power goes out, we lose the phone line. And I don't realize for many days until I try to use my phone and there is no dial tone.
So after about 4 times of this (about 10 tries a piece), i think i have the steps down to get the phone light back on most reliably.
Turn off the power to all of it.
Disconnect the hot spot router from the cable modem.
Go ahead and disconnect the phone line (not sure if this matters)
Disconnect the cable coaxial cable from the cable modem
Plug the coaxial cable back in after oh about 15 seconds
Power on the cable modem, wait until the lights all stabilize, they seem to flash, and do something for a bit, then when the Cable indicator has been solid for a good few seconds
Power on the hot spot router
connect the router back up to the cable modem
connect the phone line, wait, it takes up to 2 minutes for the blue light to come on
If this does not work, repeat again and again and I promise it will eventually work!!! Every time I get mad and give up, I come back then the blue light comes on!!
So after about 4 times of this (about 10 tries a piece), i think i have the steps down to get the phone light back on most reliably.
Turn off the power to all of it.
Disconnect the hot spot router from the cable modem.
Go ahead and disconnect the phone line (not sure if this matters)
Disconnect the cable coaxial cable from the cable modem
Plug the coaxial cable back in after oh about 15 seconds
Power on the cable modem, wait until the lights all stabilize, they seem to flash, and do something for a bit, then when the Cable indicator has been solid for a good few seconds
Power on the hot spot router
connect the router back up to the cable modem
connect the phone line, wait, it takes up to 2 minutes for the blue light to come on
If this does not work, repeat again and again and I promise it will eventually work!!! Every time I get mad and give up, I come back then the blue light comes on!!
Thursday, June 3, 2010
Set up FTP Site on Windows 2008, using IIS 6.0!
It has been quite awhile since I've posted. I guess I've haven't done anything too interesting in the world of computers and programming until this week.
Okay, so my task this week was to move the current webserver from a Windows 2000 server to a new Windows 2008 server. Whoa! We're kinda behind! And oh my things have changed! I'll admit, at first, I totally complained off this new server layout. Hey, I knew how to navigate that old server and I kind of liked it, BUT it was dying, dying, dying. Soooo bye-bye my little server, HELLO 2008!
Okay, so I didn't do all this in a week, I prepared in the previous weeks and switched the IP address over this week, and thanked my lucky stars it went pretty smooth, a few glitches, but not too bad. EXCEPT, the FTP site. I did not originally set up the FTP site, nor have I before, so this was all new to me.
So just in case you ever need to know, here are a few actions that somehow got the FTP site to finally run:
Turn on the FTP Service using the Turn Windows Features on or off. This is kind of hidden in my opinion. It is located inside the Server Manager as a Role in the Web Services area.
Create your FTP Site:
Inside the IIS Manager, Click FTP Sites, it will guide you through a link to open the IIS 6.0 manager.
Under FTP Site, add a new site. In my case i used the Isolated Users option, due to the fact that at this time we are using a Windows 2000 server to host our Active Directory, it appeared there was more setup to do on that server if I wanted to use the Active Directory, and since it will be upgraded soon, I chose to use the plain jane Isolated Users.
Now, some tricky parts.
Problem 1: Could not connect to the ftp site from my browser or command line or filezilla....
Resolution: Open Ports. Using an elevated command prompt, I ran the following command on the server:
netsh advfirewall firewall add rule name="FTP (non-SSL)" action=allow protocol=TCP dir=in localport=21
Also, I ran this one for FTP dynamic ports (umm..whatever that means, I just follow instructions):
netsh advfirewall set global StatefulFtp enable
Next, I had to open up the ports in the Firewall, so I opened up the Firewall, Server Manager - Go To Firewall Properties - Windows Firewall Properties - Inbound Rules
Add a new rule. (located on the right side of interface);
Under rule type select the radio for "Port" and hit next
Select the radio for "Specific Local Ports". Typed the range out separating each port with a comma (I think I did 5500-5525). And hit next
Then, I set up the passive ftp port range, again whatever, just follow the instructions:
since, i'm in IIS 6.0, in an elevated command prompt, go to c:\inetpub\AdminScripts, then run:
adsutil.vbs set /MSFTPSVC/PassivePortRange "5500-5525"
Okay, so port now open.
Problem 2: Setting up an FTP folder. This is where it is so complicated until you know what the heck is going on.
In this site, I need to allow anonymous access and allow users to log in to certain folders.
When setting up these folder, you have to be aware that there are Virtual Directories and Physical Directories, these are coupled together, especially in naming convention! It appears Windows FTP does some sort of name matching, for the domain name and user name, or just the user name for local users.
The physical directory:
For anonymous users, you set up the following under your root ftp directory (mine was c:\inetpub\ftproot), maybe this isn't safe but it works...
in that folder, you must create this structure so that anonymous users are automatically "dropped" into there:
c:\inetpub\ftproot\LocalUser\Public
On the physical folder, the IUSR_XXXX account (account used to anonymously access the site), needs to have whatever appropriate permission, read, write, list on the public folder or folders created under it.
Next, my domain users needed access to their folders. To do this, i had to create a folder under the root named the same as the domain name:
c:\inetpub\ftproot\junk-domain-name
For each user, i created a folder named their login name:
c:\inetpub\ftproot\junk-domain-name\user-name
**on the physical folder add NTFS permissions for the specific user, with the appropriate permissions - read, write, whatever.**
Next set up the users network folder:
Inside the user's folder, i had to create a dummy folder
c:\inetpub\ftproot\junk-domain-name\user-name\dummy-folder-name
Okay now the Virtual Directory Hook-Up:
(we don't need to do anything else for the anonymous folder, apparently, Windows takes care of that after you create the right physical folders.)
for each domain user that has a folder, you will need to create a Virtual Directory that points to that folder and named the SAME as that folder name:
So, I created the VD: junk-domain-name, that points to c:\inetpub\ftproot\junk-domain-name
Also, for the access to the network folder, i had to create a VD, with the same name as the dummy folder name:
So, I created the VD: dummy-folder-name, that points to the NETWORK PATH \\network-file-share-name\junk-name
Ah, so I think those were the steps, this took me roughly 3 days to do. I thought it was going to be way easier than all this but i did learn alot!
Hope that helps someone!!
Okay, so my task this week was to move the current webserver from a Windows 2000 server to a new Windows 2008 server. Whoa! We're kinda behind! And oh my things have changed! I'll admit, at first, I totally complained off this new server layout. Hey, I knew how to navigate that old server and I kind of liked it, BUT it was dying, dying, dying. Soooo bye-bye my little server, HELLO 2008!
Okay, so I didn't do all this in a week, I prepared in the previous weeks and switched the IP address over this week, and thanked my lucky stars it went pretty smooth, a few glitches, but not too bad. EXCEPT, the FTP site. I did not originally set up the FTP site, nor have I before, so this was all new to me.
So just in case you ever need to know, here are a few actions that somehow got the FTP site to finally run:
Turn on the FTP Service using the Turn Windows Features on or off. This is kind of hidden in my opinion. It is located inside the Server Manager as a Role in the Web Services area.
Create your FTP Site:
Inside the IIS Manager, Click FTP Sites, it will guide you through a link to open the IIS 6.0 manager.
Under FTP Site, add a new site. In my case i used the Isolated Users option, due to the fact that at this time we are using a Windows 2000 server to host our Active Directory, it appeared there was more setup to do on that server if I wanted to use the Active Directory, and since it will be upgraded soon, I chose to use the plain jane Isolated Users.
Now, some tricky parts.
Problem 1: Could not connect to the ftp site from my browser or command line or filezilla....
Resolution: Open Ports. Using an elevated command prompt, I ran the following command on the server:
netsh advfirewall firewall add rule name="FTP (non-SSL)" action=allow protocol=TCP dir=in localport=21
Also, I ran this one for FTP dynamic ports (umm..whatever that means, I just follow instructions):
netsh advfirewall set global StatefulFtp enable
Next, I had to open up the ports in the Firewall, so I opened up the Firewall, Server Manager - Go To Firewall Properties - Windows Firewall Properties - Inbound Rules
Add a new rule. (located on the right side of interface);
Under rule type select the radio for "Port" and hit next
Select the radio for "Specific Local Ports". Typed the range out separating each port with a comma (I think I did 5500-5525). And hit next
Then, I set up the passive ftp port range, again whatever, just follow the instructions:
since, i'm in IIS 6.0, in an elevated command prompt, go to c:\inetpub\AdminScripts, then run:
adsutil.vbs set /MSFTPSVC/PassivePortRange "5500-5525"
Okay, so port now open.
Problem 2: Setting up an FTP folder. This is where it is so complicated until you know what the heck is going on.
In this site, I need to allow anonymous access and allow users to log in to certain folders.
When setting up these folder, you have to be aware that there are Virtual Directories and Physical Directories, these are coupled together, especially in naming convention! It appears Windows FTP does some sort of name matching, for the domain name and user name, or just the user name for local users.
The physical directory:
For anonymous users, you set up the following under your root ftp directory (mine was c:\inetpub\ftproot), maybe this isn't safe but it works...
in that folder, you must create this structure so that anonymous users are automatically "dropped" into there:
c:\inetpub\ftproot\LocalUser\Public
On the physical folder, the IUSR_XXXX account (account used to anonymously access the site), needs to have whatever appropriate permission, read, write, list on the public folder or folders created under it.
Next, my domain users needed access to their folders. To do this, i had to create a folder under the root named the same as the domain name:
c:\inetpub\ftproot\junk-domain-name
For each user, i created a folder named their login name:
c:\inetpub\ftproot\junk-domain-name\user-name
**on the physical folder add NTFS permissions for the specific user, with the appropriate permissions - read, write, whatever.**
Next set up the users network folder:
Inside the user's folder, i had to create a dummy folder
c:\inetpub\ftproot\junk-domain-name\user-name\dummy-folder-name
Okay now the Virtual Directory Hook-Up:
(we don't need to do anything else for the anonymous folder, apparently, Windows takes care of that after you create the right physical folders.)
for each domain user that has a folder, you will need to create a Virtual Directory that points to that folder and named the SAME as that folder name:
So, I created the VD: junk-domain-name, that points to c:\inetpub\ftproot\junk-domain-name
Also, for the access to the network folder, i had to create a VD, with the same name as the dummy folder name:
So, I created the VD: dummy-folder-name, that points to the NETWORK PATH \\network-file-share-name\junk-name
Ah, so I think those were the steps, this took me roughly 3 days to do. I thought it was going to be way easier than all this but i did learn alot!
Hope that helps someone!!
Subscribe to:
Posts (Atom)