Ian Mercer posted a similar solution as this on Phil Haack's blog:
foreach (var item in Model.Select((value, i) => new { i, value }))
{
var value = item.value;
var index = item.i;
}
This gets you the item (item.value
) and its index (item.i
) by using this overload of LINQ's Select
:
the second parameter of the function [inside Select] represents the index of the source element.
The new { i, value }
is creating a new anonymous object.
Heap allocations can be avoided by using ValueTuple
if you're using C# 7.0 or later:
foreach (var item in Model.Select((value, i) => ( value, i )))
{
var value = item.value;
var index = item.i;
}
You can also eliminate the item.
by using automatic destructuring:
<ol>
foreach ((MyType value, Int32 i) in Model.Select((value, i) => ( value, i )))
{
<li id="item_@i">@value</li>
}
</ol>
I got it to work, but the solution is a bit complex, so bear with me.
What's happening
As it is, Internet Explorer gives lower level of trust to IFRAME pages (IE calls this "third-party" content). If the page inside the IFRAME doesn't have a Privacy Policy, its cookies are blocked (which is indicated by the eye icon in status bar, when you click on it, it shows you a list of blocked URLs).
(source: piskvor.org)
In this case, when cookies are blocked, session identifier is not sent, and the target script throws a 'session not found' error.
(I've tried setting the session identifier into the form and loading it from POST variables. This would have worked, but for political reasons I couldn't do that.)
It is possible to make the page inside the IFRAME more trusted: if the inner page sends a P3P header with a privacy policy that is acceptable to IE, the cookies will be accepted.
How to solve it
Create a p3p policy
A good starting point is the W3C tutorial. I've gone through it, downloaded the IBM Privacy Policy Editor and there I created a representation of the privacy policy and gave it a name to reference it by (here it was policy1
).
NOTE: at this point, you actually need to find out if your site has a privacy policy, and if not, create it - whether it collects user data, what kind of data, what it does with it, who has access to it, etc. You need to find this information and think about it. Just slapping together a few tags will not cut it. This step cannot be done purely in software, and may be highly political (e.g. "should we sell our click statistics?").
(e.g. "the site is operated by ACME Ltd., it uses anonymous per-session identifiers for its operation, collects user data only if explicitly permitted and only for the following purposes, the data is stored only as long as necessary, only our company has access to it, etc. etc.").
(When editing with this tool, it's possible to view errors/omissions in the policy. Also very useful is the tab "HTML Policy": at the bottom, it has a "Policy Evaluation" - a quick check if the policy will be blocked by IE's default settings)
The Editor exports to a .p3p file, which is an XML representation of the above policy. Also, it can export a "compact version" of this policy.
Link to the policy
Then a Policy Reference file (http://example.com/w3c/p3p.xml
) was needed (an index of privacy policies the site uses):
<META>
<POLICY-REFERENCES>
<POLICY-REF about="/w3c/example-com.p3p#policy1">
<INCLUDE>/</INCLUDE>
<COOKIE-INCLUDE/>
</POLICY-REF>
</POLICY-REFERENCES>
</META>
The <INCLUDE>
shows all URIs that will use this policy (in my case, the whole site). The policy file I've exported from the Editor was uploaded to http://example.com/w3c/example-com.p3p
Send the compact header with responses
I've set the webserver at example.com to send the compact header with responses, like this:
HTTP/1.1 200 OK
P3P: policyref="/w3c/p3p.xml", CP="IDC DSP COR IVAi IVDi OUR TST"
// ... other headers and content
policyref
is a relative URI to the Policy Reference file (which in turn references the privacy policies), CP
is the compact policy representation. Note that the combination of P3P headers in the example may not be applicable on your specific website; your P3P headers MUST truthfully represent your own privacy policy!
Profit!
In this configuration, the Evil Eye does not appear, the cookies are saved even in the IFRAME, and the application works.
Edit: What NOT to do, unless you like defending from lawsuits
Several people have suggested "just slap some tags into your P3P header, until the Evil Eye gives up".
The tags are not only a bunch of bits, they have real world meanings, and their use gives you real world responsibilities!
For example, pretending that you never collect user data might make the browser happy, but if you actually collect user data, the P3P is conflicting with reality. Plain and simple, you are purposefully lying to your users, and that might be criminal behavior in some countries. As in, "go to jail, do not collect $200".
A few examples (see p3pwriter for the full set of tags):
- NOI : "Web Site does not collected identified data." (as soon as there's any customization, a login, or any data collection (***** Analytics, anyone?), you must acknowledge it in your P3P)
- STP: Information is retained to meet the stated purpose. This requires information to be discarded at the earliest time possible. Sites MUST have a retention policy that establishes a destruction time table. The retention policy MUST be included in or linked from the site's human-readable privacy policy." (so if you send
STP
but don't have a retention policy, you may be committing fraud. How cool is that? Not at all.)
I'm not a lawyer, but I'm not willing to go to court to see if the P3P header is really legally binding or if you can promise your users anything without actually willing to honor your promises.
Best Answer
[UPDATE] I'm updating this answer to work with Internet Explorer 11, in Windows 10 x64 with Visual Studio 2017 Community. The previous version of this answer (for Internet Explorer 8, in Windows 7 x64 and Visual Studio 2010) is at the bottom of this answer.
Creating a Working Internet Explorer 11 Add-on
I am using Visual Studio 2017 Community, C#, .Net Framework 4.6.1, so some of these steps might be slightly different for you.
You need to open Visual Studio as Administrator to build the solution, so that the post-build script can register the BHO (needs registry access).
Start by creating a class library. I called mine InternetExplorerExtension.
Add these references to the project:
"Microsoft Internet Controls"
"Microsoft.mshtml"
Note: Somehow MSHTML was not registered in my system, even though I could find in in the Add Reference window. This caused an error while building:
The fix can be found at http://techninotes.blogspot.com/2016/08/fixing-cannot-find-wrapper-assembly-for.html Or, you can run this batch script:
Create the following files:
IEAddon.cs
Interop.cs
and finally a form, that we will use to configure the options. In this form place a
TextBox
and an OkButton
. Set the DialogResult of the button to Ok. Place this code in the form code:In the project properties, do the following:
C:\Program Files (x86)\Internet Explorer\iexplore.exe
http://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
In the Build Events tab, set Post-build events command line to:
Attention: even though my computer is x64, I used the path of the non-x64
gacutil.exe
and it worked... the one specific for x64 is at:64bit IE Needs 64bit-compiled and 64bit-registered BHO. Though I could only debug using 32bit IE11, the 32bit registered extension also worked by running 64bit IE11.
This answer appears to have some additional info about this: https://stackoverflow.com/a/23004613/195417
If you need to, you can use the 64bit regasm:
How this add-on works
I didn't change the behavior of the add-on... take a look at IE8 section bellow for description.
## Previous Answer for IE8
Man... this has been a lot of work! I was so curious about how to do this, that I did it myself.
First of all... credit is not all mine. This is a compilation of what I found, on these sites:
And of course, I wanted my answer to have the features you asked:
I will describe it step by step, how I managed to do it working with Internet Explorer 8, in Windows 7 x64... note that I could not test in other configurations. Hope you understand =)
Creating a Working Internet Explorer 8 Add-on
I am using Visual Studio 2010, C# 4, .Net Framework 4, so some of these steps might be slightly different for you.
Created a class library. I called mine InternetExplorerExtension.
Add these references to the project:
Note: These references may be in different places in each computer.
this is what my references section in csproj contains:
Create the files the same way as the updated IE11 files.
IEAddon.cs
You can uncomment the following lines from IE11 version:
Interop.cs
Same as IE11 version.
and finally a form, that we will use to configure the options. In this form place a
TextBox
and an OkButton
. Set the DialogResult of the button to Ok. The code is the same for IE11 addon.In the project properties, do the following:
C:\Program Files (x86)\Internet Explorer\iexplore.exe
http://msdn.microsoft.com/en-us/library/ms976373.aspx#bho_getintouch
In the Build Events tab, set Post-build events command line to:
Attention: as my computer is x64, there is a specific x64 inside the path of gacutil executable on my machine that may be different on yours.
64bit IE Needs 64bit-compiled and 64bit-registered BHO. Use 64bit RegAsm.exe (usually lives in C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe)
How this add-on works
It traverses all DOM tree, replacing the text, configured using the button, by itself with a yellow background. If you click on the yellowed texts, it calls a javascript function that was inserted on the page dynamically. The default word is 'browser', so that it matches a lot of them! EDIT: after changing the string to be highlighted, you must click the URL box and press Enter... F5 will not work, I think that it is because F5 is considered as 'navigation', and it would require to listen to navigate event (maybe). I'll try to fix that later.
Now, it is time to go. I am very tired. Feel free to ask questions... may be I will not be able to answer since I am going on a trip... in 3 days I'm back, but I'll try to come here in the meantime.