Why does calling AutoFake.Provide() wipe out fakes already configured with A.CallTo()? - autofac

Why does calling fake.Provide<T>() wipe out fakes already configured with A.CallTo()? Is this a bug?
I'm trying to understand a problem I've run into with Autofac.Extras.FakeItEasy (aka AutoFake). I have a partial solution, but I don't understand why my original code doesn't work. The original code is complicated, so I've spent some time simplifying it for the purposes of this question.
Why does this test fail? (working DotNetFiddle)
public interface IStringService { string GetString(); }
public static void ACallTo_before_Provide()
{
using (var fake = new AutoFake())
{
A.CallTo(() => fake.Resolve<IStringService>().GetString())
.Returns("Test string");
fake.Provide(new StringBuilder());
var stringService = fake.Resolve<IStringService>();
string result = stringService.GetString();
// FAILS. The result should be "Test string",
// but instead it's an empty string.
Console.WriteLine($"ACallTo_before_Provide(): result = \"{result}\"");
}
}
If I swap the order of the calls to fake.Provide<T>() and A.CallTo(), it works:
public static void Provide_before_ACallTo()
{
// Same code as above, but with the calls to
// fake.Provide<T>() and A.CallTo() swapped
using (var fake = new AutoFake())
{
fake.Provide(new StringBuilder());
A.CallTo(() => fake.Resolve<IStringService>().GetString())
.Returns("Test string");
var stringService = fake.Resolve<IStringService>();
string result = stringService.GetString();
// SUCCESS. The result is "Test string" as expected
Console.WriteLine($"Provide_before_ACallTo(): result = \"{result}\"");
}
}
I know what is happening, sort of, but I'm not sure if it's intentional behavior or if it's a bug.
What is happening is, the call to fake.Provide<T>() is causing anything configured with A.CallTo() to be lost. As long as I always call A.CallTo() after fake.Provide<T>(), everything works fine.
But I don't understand why this should be.
I can't find anything in the documentation stating that A.CallTo() cannot be called before Provide<T>().
Likewise, I can't find anything suggesting Provide<T>() cannot be used with A.CallTo().
It seems the order in which you configure unrelated dependencies shouldn't matter.
Is this a bug? Or is this the expected behavior? If this is the expected behavior, can someone explain why it works like this?

It isn't that the Fake's configuration is being changed. In the first test, Resolve is returning different Fakes each time it's called. (Check them for reference equality; I did.)
Provide creates a new scope and pushes it on a stack. The topmost scope is used by Resolve when it finds an object to return. I think this is why you're getting different Fakes in ACallTo_before_Provide.
Is this a bug? Or is this the expected behavior? If this is the expected behavior, can someone explain why it works like this?
It's not clear to me. I'm not an Autofac user, and don't understand why an additional scope is introduced by Provide. The stacked scope behaviour was introduced in PR 18. Perhaps the author can explain why.
In the meantime, if possible, I'd Provide all you need to before Resolveing, if you can manage it.

Related

solidity v0.8.15 : require & mapping issues on ETH mainnet

I'm working on a NFT management contrat; I can see everything works fine on rinkeby testnet, but when I'm calling the same functions on mainnet, I get errors many false errors with require. code was compiled on REMIX Ide;
Here is an example:
mapping(address => mapping(uint => uint8) public handledNfts;
mapping(bytes32 => uint8) public usedHashes;
function create(address contractAddress, uint tokenId, bytes32 hash) external
{
uint8 vCheck = usedHashes[hash];
require(vCheck!=1, "Bad hash"); // sometimes it has false-positive
usedHashes[ hash ] = 1;
uint8 vCheck = handledNfts[contractAddress][tokenId];
require(vCheck!=1, "Already created"); // False-positive sometimes also
handledNfts[contractAddress][tokenId] = 1;
//--- DO SOMETHING ....
}
So when I'm on rinkeby any call to create will work.
However on mainnet, the create function returns a "Bad hash" or "Already closed" for no real reason, but sometimes in works like a charm.
So I don't know what's the problem on mainnet for a code which works fine from testnet?
It's strange because the
handledNfts[contractAddress][tokenId] should not be at ==1 when starting using the contrat.
However solidity says the hash has already been used or the nft says to be already managed, when it's not true.
Sometimes it works and sometimes it doesn't. Most of the time it doesn't
The hash using in the create function is always unique for each call.
Can someone help me find a solution on that instability, please?
It seems like mapping objects with a require don't work properly with me.
I compile the code through remix directly, with solidity v0.8.15
https://remix.ethereum.org/#optimize=true&runs=200&evmVersion=null&version=soljson-v0.8.15+commit.e14f2714.js
stangely also, I'm forced to use a variable to access a mapping object then use that variable; so a code like this is buggy on me many time:
require(usedHashes[hash]!=1, "Hash already used"); <-- buggy on mainnet
Any help please?
I understand what happened. I've been front-runned by a MEV BOT. It detected an ETH transaction was sent from my smartcontract, and sent a copy-cat of the transaction earlier than mine.
I've put counter-actions to avoid it. it's okay now.

All string data appears as "Instance of" when i print

recently i made a couple of form pages( text input,radio button, that kind of stuff), and they used to work pretty well. I came back to them after working in another part of the app, and realize that it doesn't work anymore.
I checked a couple of things and realized that all text input data comes as "Instance of thing". So when i send the data to the backend and check it, it appears as null. As far as i know this means that the string data the user input is not being saved as a string inside my variables, but as instances and that's why it doesn't work.
Any ideas as to why this happened? As far as i remember i didn't change anything in these pages.
I'm using provider to maintain the data locally.
If snippets of code are needed please ask.
Most probably if you are getting "Instance of thing" & also null, then you need to await on your data.
class YourClass {
int yourVariable = 0;
String anotherVariable = "string";
#override
String toString() {
return "YourVariable : $yourVariable , AnotherVariable : $anotherVariable";
}
}
You have to override the toString() method and return your objects like above and call toString() method when you print the object

Issue with eclipse: Potential null pointed analysis

May be, This has been discussed many times. But, I am not clear on how #javax.annotation.nullable and notnull works in Eclipse. I have the below code in eclipse.
if(null != getApplicant()){
name = getApplicant().getName(); //Potential null pointer access
}
Wherein, getApplication() is annotated with #Nullable.
In the above code, I have verified against null before accessing it. But, still I get error here by compiler. The same code works fine Intellij. (Most of the developers in my team use this :().
Kindly tell me how can I get this #javax.annotation.Nullable and #javax.annotation.Notnull worked in eclipse in similar way to Intellij. I dont want to change my IDE just for this different behavior.
There's no assurance to the compiler that calling getApplication() the second time returns a non-null result as it did the first time. Store it in a local for the test and then use that within the if block.
Eclipse warns you, that the second method access could potentially return null. Example code to reproduce nullpointer:
public class A {
int numberCalls;
Applicant getApplicant() {
if (numberCalls++ > 3)
return null;
else
return new Applicant();
}
}
I would suggest to implement your call like this:
Applicant applicant = getApplicant();
if(null != applicant){
name = applicant.getName(); //not anymore Potential null pointer access
}

Breeze: cannot execute _executeQueryCore until metadataStore is populated

I was using Breeze v1.1.2 that came with the Hot Towel template which has now been extended to form my project. I made the mistake of updating the NuGet package to the current 1.3.3 (I never learn). Anyway, all was well, and now not so much!
I followed the instructions in the release notes and other docs to change my BreezeWebApiConfig file to:
[assembly: WebActivator.PreApplicationStartMethod(
typeof(BreezeWebApiConfig), "RegisterBreezePreStart")]
namespace MyApp.App_Start {
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "breeze/{controller}/{action}"
);}}}
And the config.js file (which provides the serviceName to the EntityManager constructor) to:
var remoteServiceName = 'breeze/breeze'; // NEW version
//var remoteServiceName = 'api/breeze'; // OLD version
And my BreezeController if you're interested:
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<MyDbContext> _contextProvider =
new EFContextProvider<MyDbContext>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpGet]
public IQueryable<SomeItem> SomeItems()
{
// Do stuff here...
}
}
Now I get the "cannot execute _executeQueryCore until metadataStore is populated" error.
What am I missing here?
EDIT:
I perhaps left out the part you needed... Above in the SomeItems() method, the stuff that actually gets done is a call to the GetMeSomeData() method in the MyDBContext class. This method makes the following call to a stored procedure to get the data.
public virtual ObjectResult<SomeItem> GetMeSomeData(string inParam)
{
var p = new object[] { new SqlParameter("#inParam", inParam) };
var retVal = ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<SomeItem>("exec GetData #SN", p);
return retVal;
}
Now given my limited understanding, the call to Metadata() is not failing, but I don't think it has any idea what the entity model is when coming back, even though somewhere along the line, it should figure that out from the entity model I do have (i.e. SomeItem)? The return string from Metadata() doesn't have any information about the entity. Is there a way to make it aware? Or am I just completely off in left field playing with the daisies?
Hard to say based on this report. Let's see if Breeze is right.
Open the browser debugging tools and look at the network traffic. Do you see an attempt to get metadata from the server before you get that error? If so, did it succeed? Or 404? Or 500? What was the error?
I'm betting it didn't even try. If it didn't, the usual reason is that you tried some Breeze operation before your first query ... and you didn't ask for metadata explicitly either. Did you try to create an entity? That requires metadata.
The point is, you've got to track down the Breeze operation that precipitates the error. Sure everything should just work. The world should be rainbows and unicorns. When it isn't, we heave a sigh, break out the debugger, and start with the information that the error gave us.
And for the rest of you out there ... upgrading to a new Breeze version is a good thing.
Happy coding everyone.
Follow-up to your update
Breeze doesn't know how you get your data on the back-end. If the query result has a recognizable entity in it, Breeze will cache that. It's still up to you in the query callback to ensure that what you deliver to the caller is something meaningful.
You say that you're server-side metadata method doesn't have any idea what SomeItem is? Then it's not much use to the client. If it returns a null string, Breeze may treat that as "no metadata at all" in which case you should be getting the "cannot execute _executeQueryCore until metadataStore is populated" error message. Btw, did you check the network traffic to determine what your server actually returned in response to the metadata request (or if there was such a request)?
There are many ways to create Metadata on the server. The easiest is to use EF ... at least as a modeling tool at design time. What's in that MyDbContext of yours? Why isn't SomeItem in there?
You also can create metadata on the client if you don't want to generate it from the server. You do have to tell the Breeze client that you've made that choice. Much of this is explained in the documentation "Metadata Format".
I get the feeling that you're kind of winging it. You want to stray from the happy path ... and that's cool. But most of us need to learn to walk before we run.

Enforce Hyphens in .NET MVC 4.0 URL Structure

I'm looking specifically for a way to automatically hyphenate CamelCase actions and views. That is, I'm hoping I don't have to actually rename my views or add decorators to every ActionResult in the site.
So far, I've been using routes.MapRouteLowercase, as shown here. That works pretty well for the lowercase aspect of URL structure, but not hyphens. So I recently started playing with Canonicalize (install via NuGet), but it also doesn't have anything for hyphens yet.
I was trying...
routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();
My regular expression definitely works the way I want it to as far as restructuring the URL properly, but those URLs aren't identified, of course. The file is still ChangePassword.cshtml, for example, so /account/change-password isn't going to point to that.
BTW, I'm still a bit rusty with .NET MVC. I haven't used it for a couple years and not since v2.0.
This might be a tad bit messy, but if you created a custom HttpHandler and RouteHandler then that should prevent you from having to rename all of your views and actions. Your handler could strip the hyphen from the requested action, which would change "change-password" to changepassword, rendering the ChangePassword action.
The code is shortened for brevity, but the important bits are there.
public void ProcessRequest(HttpContext context)
{
string controllerId = this.requestContext.RouteData.GetRequiredString("controller");
string view = this.requestContext.RouteData.GetRequiredString("action");
view = view.Replace("-", "");
this.requestContext.RouteData.Values["action"] = view;
IController controller = null;
IControllerFactory factory = null;
try
{
factory = ControllerBuilder.Current.GetControllerFactory();
controller = factory.CreateController(this.requestContext, controllerId);
if (controller != null)
{
controller.Execute(this.requestContext);
}
}
finally
{
factory.ReleaseController(controller);
}
}
I don't know if I implemented it the best way or not, that's just more or less taken from the first sample I came across. I tested the code myself so this does render the correct action/view and should do the trick.
I've developed an open source NuGet library for this problem which implicitly converts EveryMvc/Url to every-mvc/url.
Uppercase urls are problematic because cookie paths are case-sensitive, most of the internet is actually case-sensitive while Microsoft technologies treats urls as case-insensitive. (More on my blog post)
NuGet Package: https://www.nuget.org/packages/LowercaseDashedRoute/
To install it, simply open the NuGet window in the Visual Studio by right clicking the Project and selecting NuGet Package Manager, and on the "Online" tab type "Lowercase Dashed Route", and it should pop up.
Alternatively, you can run this code in the Package Manager Console:
Install-Package LowercaseDashedRoute
After that you should open App_Start/RouteConfig.cs and comment out existing route.MapRoute(...) call and add this instead:
routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
new DashedRouteHandler()
)
);
That's it. All the urls are lowercase, dashed, and converted implicitly without you doing anything more.
Open Source Project Url: https://github.com/AtaS/lowercase-dashed-route
Have you tried working with the URL Rewrite package? I think it pretty much what you are looking for.
http://www.iis.net/download/urlrewrite
Hanselman has a great example herE:
http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx
Also, why don't you download something like ReSharper or CodeRush, and use it to refactor the Action and Route names? It's REALLY easy, and very safe.
It would time well spent, and much less time overall to fix your routing/action naming conventions with an hour of refactoring than all the hours you've already spent trying to alter the routing conventions to your needs.
Just a thought.
I tried the solution in the accepted answer above: Using the Canonicalize Pattern url strategy, and then also adding a custom IRouteHandler which then returns a custom IHttpHandler. It mostly worked. Here's one caveat I found:
With the typical {controller}/{action}/{id} default route, a controller named CatalogController, and an action method inside it as follows:
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
I noticed that requests to "/catalog/quick-select/1234" worked perfectly, but requests to /catalog/quick-select?id=1234 were 500'ing because once the action method was called as a result of controller.Execute(), the id parameter was null inside of the action method.
I do not know exactly why this is, but the behavior was as if MVC was not looking at the query string for values during model binding. So something about the ProcessRequest implementation in the accepted answer was screwing up the normal model binding process, or at least the query string value provider.
This is a deal breaker, so I took a look at default MVC IHttpHandler (yay open source!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
I will not pretend that I grok'ed it in its entirety, but clearly, it's doing ALOT more in its implementation of ProcessRequest than what is going on in the accepted answer.
So, if all we really need to do is strip dashes from our incoming route data so that MVC can find our controllers/actions, why do we need to implement a whole stinking IHttpHandler? We don't! Simply rip out the dashes in the GetHttpHandler method of DashedRouteHandler and pass the requestContext along to the out of the box MvcHandler so it can do its 252 lines of magic, and your route handler doesn't have to return a second rate IHttpHandler.
tl:dr; - Here's what I did:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}