I just took over a bunch of C# code from another company, and I'm having big trouble getting the first build to work. The code uses a framework called Nancy, instead of MVC. I have never used this framework before, and there might be a real simply answer to my question, and I apllogize if I missed some basic understanding of Nancy, before posting here.
The problem is boiled down to a single class, handling the initialization of the application (I THINK) From what I've read, it's pretty standard Nancy:
using System;
using Nancy;
using NewRelicAgent = NewRelic.Api.Agent.NewRelic;
using Nancy.Bootstrapper;
using Nancy.Routing;
public class NewRelicStartup : IApplicationStartup
{
private readonly IRouteResolver routeResolver;
public NewRelicStartup (IRouteResolver routeResolver)
{
this.routeResolver = routeResolver;
}
public void Initialize(IPipelines pipelines)
{
pipelines.BeforeRequest.AddItemToStartOfPipeline(
context =>
{
var route = routeResolver.Resolve(context);
if (route == null || route.Item1 == null || route.Item1.Description == null) // probably not necessary but don't want the chance of losing visibility on anything
{
NewRelicAgent.SetTransactionName(
context.Request.Method,
context.Request.Url.ToString());
}
else
{
NewRelicAgent.SetTransactionName(
route.Item1.Description.Method,
route.Item1.Description.Path);
}
return null;
});
pipelines.OnError.AddItemToEndOfPipeline(
(context, ex) => {
NewRelicAgent.NoticeError(ex);
return null;
}
);
}
}
When this code is being build, I get several errors, some of which being:
Delegate 'System.Func<Nancy.NancyContext,System.Threading.CancellationToken,System.Threading.Tasks.Task<Nancy.Response>>' does not take 1 arguments
Cannot convert lambda expression to type 'Nancy.PipelineItem<System.Func<Nancy.NancyContext,System.Threading.CancellationToken,System.Threading.Tasks.Task<Nancy.Response>>>' because it is not a delegate type
Here is a screenshot of the kind of error I get:
https://www.dropbox.com/s/cigcfc4sfj8batg/Nancy%20Error.PNG
I am 100 % certain, that this is some kind of interpretation issue from Visual Studio's side, since the code is live atm. I just can't build it in VS.
Do any of you have any idea what I am missing, or doing wrong? Remember; the code is working and live atm.
Try changing "return null;" to "return (Nancy.Response)null;"
Edit: Sorry, just looked at the screenshot - it's using some properties that have changed in 0.20, so you will either have to manually fix up the code (it's now async at the core), or roll back to 0.19 for now, and re-write that bit of code at a later date.
Edit again: Give this ago:
pipelines.BeforeRequest.AddItemToStartOfPipeline(
context =>
{
var route = routeResolver.Resolve(context);
if (route == null || route.Route == null || route.Route.Description == null) // probably not necessary but don't want the chance of losing visibility on anything
{
NewRelicAgent.SetTransactionName(
context.Request.Method,
context.Request.Url.ToString());
}
else
{
NewRelicAgent.SetTransactionName(
route.Route.Description.Method,
route.Route.Description.Path);
}
return null;
});
Related
I'm new to using entity as a data layer between MVC and SQL Server, so I apologize up front if what I'm doing is bad practice.
Let me start by sharing the code that is handling the update.
Update Delivery:
public bool One(Delivery toUpdate)
{
using (var dbContext = new FDb())
{
try
{
var deliveryInDb = this.dbTable(dbContext).Single(x => x.DeliveryId == toUpdate.DeliveryId);
dbContext.Entry(deliveryInDb).CurrentValues.SetValues(toUpdate);
//removal first
List<DeliveryDay> currentDays = FEngineCore.DeliveryDay.Get.ForValue((x => x.DeliveryId), toUpdate.DeliveryId);
List<DeliveryTime> currentTimes = FEngineCore.DeliveryTime.Get.ForValue((x => x.DeliveryId), toUpdate.DeliveryId);
//remove delivery days that are not needed
foreach (var curDay in currentDays)
{
if (!toUpdate.DeliveryDays.Select(x => x.DeliveryDayId).Contains(curDay.DeliveryDayId))
{
FEngineCore.DeliveryDay.Delete.One((x => x.DeliveryDayId), curDay.DeliveryDayId);
deliveryInDb.DeliveryDays.Remove(curDay);
}
}
//remove delivery times that are not needed
foreach (var curTime in currentTimes)
{
if (!toUpdate.DeliveryTimes.Select(x => x.DeliveryTimeId).Contains(curTime.DeliveryTimeId))
{
FEngineCore.DeliveryTime.Delete.One((x => x.DeliveryTimeId), curTime.DeliveryTimeId);
deliveryInDb.DeliveryTimes.Remove(curTime);
}
}
foreach (var day in toUpdate.DeliveryDays)
{
if (day.DeliveryDayId == 0)
{
dbContext.DeliveryDays.Add(day);
}
else
{
if (dbContext.DeliveryDays.Local.Any(e => e.DeliveryDayId == day.DeliveryDayId))
{
dbContext.Entry(dbContext.DeliveryDays.Local.First(e => e.DeliveryDayId == day.DeliveryDayId)).CurrentValues.SetValues(day);
dbContext.Entry(dbContext.DeliveryDays.Local.First(e => e.DeliveryDayId == day.DeliveryDayId)).State = EntityState.Modified;
}
else
{
DeliveryDay modDay = new DeliveryDay
{
DayOfWeek = day.DayOfWeek,
DeliveryDayId = day.DeliveryDayId,
DeliveryId = day.DeliveryId,
Interval = day.Interval
};
dbContext.DeliveryDays.Attach(modDay);
dbContext.Entry(modDay).State = EntityState.Modified;
}
deliveryInDb.DeliveryDays.Add(day);
}
}
foreach (var time in toUpdate.DeliveryTimes)
{
if (time.DeliveryTimeId == 0)
{
dbContext.DeliveryTimes.Add(time);
}
else
{
if (dbContext.DeliveryTimes.Local.Any(e => e.DeliveryTimeId == time.DeliveryTimeId))
{
dbContext.Entry(dbContext.DeliveryTimes.Local.First(e => e.DeliveryTimeId == time.DeliveryTimeId)).CurrentValues.SetValues(time);
dbContext.Entry(dbContext.DeliveryTimes.Local.First(e => e.DeliveryTimeId == time.DeliveryTimeId)).State = EntityState.Modified;
}
else
{
DeliveryTime modTime = new DeliveryTime
{
DeliveryId = time.DeliveryId,
DeliveryLocationId = time.DeliveryLocationId,
DeliveryTimeId = time.DeliveryTimeId,
DropoffTime = time.DropoffTime
};
dbContext.DeliveryTimes.Attach(modTime);
dbContext.Entry(modTime).State = EntityState.Modified;
}
deliveryInDb.DeliveryTimes.Add(time);
}
}
dbContext.SaveChanges();
dbContext.Entry(deliveryInDb).State = EntityState.Detached;
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return false;
}
}
}
Let me continue by explaining that the delivery object has 2 children; DeliveryTime and DeliveryDay. The issue that arises happens when I try to remove one deliveryTime and modify nothing else. The end result of running the code normally (not in debug) is that the deliveryTime is in fact not removed. Here's the interesting thing guys, when I debug it and go through the break points, everything works as expected!
Let me continue by posting the code that is running behind the removal method of the deliveryTime (actually all entity objects in my system).
public bool One<V>(Expression<Func<T, V>> property, V value) where V : IComparable
{
using (var dbContext = new FoodsbyDb())
{
try
{
T toDelete;
//get the body as a property that represents the property of the entity object
MemberExpression entityPropertyExpression = property.Body as MemberExpression;
//get the parameter that is representing the entity object
ParameterExpression entityObjectExpression = (ParameterExpression)entityPropertyExpression.Expression;
//represent the value being checked against as an expression constant
Expression valueAsExpression = Expression.Constant(value);
//check the equality of the property and the value
Expression equalsExpression = Expression.Equal(entityPropertyExpression, valueAsExpression);
//create an expression that takes the entity object as a parameter, and checks the equality using the equalsExpression variable
Expression<Func<T, bool>> filterLambda = Expression.Lambda<Func<T, bool>>(equalsExpression, entityObjectExpression);
toDelete = this.dbTable(dbContext)
.SingleOrDefault(filterLambda);
if (toDelete != null)
{
this.dbTable(dbContext)
.Remove(toDelete);
dbContext.SaveChanges();
return true;
}
return false;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return false;
}
}
}
The code above is obviously generic, and it handles all my entity objects. I have tested it in and out and know for sure the problem does not lie in there. I thought it would be helpful to post it so you all can have a full understanding of what's going on.
Here's my best guess as to what's going on:
The reference to the removed deliveryTime still exists when the database context is saved, but when I debug, the system has enough time to remove the context.
Here was one of my attempted solutions:
Remove all references to the children objects immediately after setting currentDays and currentTimes and then proceeding to add them back to deliveryInDb as you enumerate through them.
Because I am new to all of this, if you see some bad practice along with the solution, I wouldn't mind constructive criticism to improve my programming method.
I actually encountered this issue in a project at work. The project is an older MVC4 project using EF 6.1.
In our situation, a simple update attempting to set a related entity property to null was failing to actually set it to null while running the web app normally (in debug mode). When setting a break point on the line of code that sets the property to null the database would be updated as expected, though. So, the update was working when a break point was in place but not working when allowed to run normally.
Using an EF interceptor, we could see that, with the break point in place, the update query was going through as expected.
Now, in our situation the related entity was using the virtual keyword to allow for lazy loading. I think this is the root of the issue. When a break point is present, EF has enough time to both lazily load that related entity and evaluate whatever it needs to evaluate and finally set it to null. When running without a break point, I think EF gets caught up trying to lazily load that entity and therefore fails to think it needs to be updated. To be clear, I was both accessing the related entity property for the first time and setting it null using a one-liner of code.
foo.Bar = null;
I resolved this issue, in our scenario, by accessing that property at least once prior to setting it to null so that EF is forced to load it. With it loaded, setting it to null seems to work as intended now. So again, to be clear, I think the issue is a combo of lazy loading and the one-liner of code both accessing that property for the first time and assigning it to null.
It appears that you're using multiple instances of your DbContext, which are not synchronized.
The solution would be to use a single instance, and pass that instance between your methods.
I've recently upgraded to Xamarin Studio running on Windows. I have a simple implementation of the mvvmcross TipCalculator tutorial that ran nicely on Android and the various Windows flavors. After I upgraded, the Android application started throwing NullReferenceExceptions in the Main activity (below):
[Activity(Label = "TipCalculator.Android", MainLauncher = true, Icon = "#drawable/icon")]
public class TipCalculatorActivity : MvxBindingActivityView<TipCalculatorViewModel>
{
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.TipView);//Throws NullReferenceException
}
}
After doing some digging into the mvvmcross code, I found this method in the MvxAndroidViewsContainer class:
public virtual IMvxViewModel Load(Intent intent, Type viewModelTypeHint)
{
if (intent == null)
{
// TODO - some trace here would be nice...
return Activator.CreateInstance(viewModelTypeHint) as IMvxViewModel;
//return null;
}
if (intent.Action == Intent.ActionMain)
{
// TODO - some trace here would be nice...
return Activator.CreateInstance(viewModelTypeHint) as IMvxViewModel;
}
if (intent.Extras == null)
{
// TODO - some trace here would be nice...
return Activator.CreateInstance(viewModelTypeHint) as IMvxViewModel;
//return null;
}
IMvxViewModel mvxViewModel;
if (TryGetEmbeddedViewModel(intent, out mvxViewModel))
return mvxViewModel;
return CreateViewModelFromIntent(intent);
}
In the original code, there are two cases that return null. In each of these I replaced that with a call to Activator.CreateInstance().
I'm not sure what the rationale behind the original implementation is, and I'm a bit concerned I've broken something. Can anybody shed some light on why there are cases this method returns null and whether I've broken something fundamental in mvvmcross?
I have no idea what your current issue has to do with the new Xamarin tools. Your description of NullReferenceExceptions, changed files and blog posts lost me...
I'd guess that quite a few things may have changed in your development setup and maybe in your app as well. If you can work back out one step at a time maybe then you'll be able to work out what the key change is.
It does sound like your code change might fix might fix your current problem - but it's definitely a patch applied after the problem (whatever it is) has occurred, so it's not something I'd want to do in the core code right now.
In terms of the code you've asked about:
if (intent == null)
{
// TODO - some trace here would be nice...
return null;
}
This first null will only occur if the Activity has somehow been created without an Intent - which I guess isn't happening? (Unless maybe somewhere in your current tooling setup this is somehow being set as null?)
if (intent.Action == Intent.ActionMain)
{
// TODO - some trace here would be nice...
return Activator.CreateInstance(viewModelTypeHint) as IMvxViewModel;
}
This is the normal path for a directly launched activity - this activity will have no extra parameters for constructing the ViewModel.
Generally this path doesn't happen in many MvvmCross apps - most apps launch via a splashscreen activity.
if (intent.Extras == null)
{
// TODO - some trace here would be nice...
return null;
}
For any other activity, Mvx should have inserted some special ViewModel information into the Extras - so there is no way Extras should be null... If this is happening, then what code is creating the activity?
IMvxViewModel mvxViewModel;
if (TryGetEmbeddedViewModel(intent, out mvxViewModel))
return mvxViewModel;
return CreateViewModelFromIntent(intent);
This is the normal launch path for an activity that has been navigated to.
If it helps, here's the latest v3 code - which has some trace added (but also adds the confusion of savedState - ignore this for now!):
public virtual IMvxViewModel Load(Intent intent, IMvxSavedState savedState, Type viewModelTypeHint)
{
if (intent == null)
{
MvxTrace.Trace(MvxTraceLevel.Error, "Null Intent seen when creating ViewModel");
return null;
}
if (intent.Action == Intent.ActionMain)
{
MvxTrace.Trace("Creating ViewModel for ActionMain");
return Activator.CreateInstance(viewModelTypeHint) as IMvxViewModel;
}
if (intent.Extras == null)
{
MvxTrace.Trace(MvxTraceLevel.Error, "Null Extras seen on Intent when creating ViewModel - this should not happen - have you tried to navigate to an MvvmCross View directly?");
return null;
}
IMvxViewModel mvxViewModel;
if (TryGetEmbeddedViewModel(intent, out mvxViewModel))
{
MvxTrace.Trace("Embedded ViewModel used");
return mvxViewModel;
}
MvxTrace.Trace("Loading new ViewModel from Intent with Extras");
return CreateViewModelFromIntent(intent, savedState);
}
How do I know the log the last property that is null?
For example,
var a = "somevalue";
......
......
if(a == null)
{
Log.Error(MethodBase.GetCurrentMethod().Name + "Property : a is null");
//blah blah
}
Like how I use the reflection to get the current method name, there should be some means by which I can log the latest local variables (or a property or fields)
that is being compared ? I use, log4net by the way to log the errors.
1) Is there any method to achieve this or should we manually log it?
2) Is there any custom method that prints the class -> MethodName -> Propertyname(or FieldName) that is null?
Thanks for your time in advance.
As mentioned by #fsimonazzi, "a" would be a local variable.
That being said there is still no way to examine the current compare operation as in MSIL there is no formal concept of an IF block - only conditional jumps.
If you wanted to get really crazy with the reflection, you may be able to find the current executing instruction and look around near that for a variable, but even then, you will not find the name - only a reference - as names are only used prior to compilation.
Either way, reflection is not going to help you here.
Instead, try using Exceptions - specifically ArgumentNullException. This body of code would become:
void doStuff(string param1, int param2)
{
if (param == null)
throw new ArgumentNullException("param1", "param1 must not be null");
if (param2 < 0)
throw new ArgumentOutOfRangeException("param2", "param2 should be non-negative.");
//method body
}
then, when you call the method, you can catch the exception and log it - no matter what it may be.
public static void Main(string[] args)
{
try
{
doStuff(null, 3);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Tools like FxCop can help make sure that you are properly validating each parameter.
Properties are actually implemented as methods, so reflection could help you there. If, for example, you were validating in a property and wanted to log the position automatically, you could.
private object _cachedObject = null;
public object CachedObject
{
get
{
if (_cachedObject == null)
{
log(MethodBase.GetCurrentMethod().Name, "creating cached object");
_cachedObject = createCachedObject();
}
return _cachedObject;
}
}
The .Net Framework 4.5 also brings with it a new attribute that can be used to replace the MethodBase.GetCurrentMethod().Name construct you are using to get the method name. See [CallerMemberNameAttribute][3].
try
{
var orderedListOfRfidTags = uow.RfidTags.ToList().OrderBy(t => int.Parse(t.Number));
return View(orderedListOfRfidTags);
}
catch
{
var orderedListOfRfidTags = uow.RfidTags.OrderBy(t => t.Number).ToList();
return View(orderedListOfRfidTags);
}
MVC3 - in Release mode this will still fail on the first line var ordreedListOfRfidTags...
I wonder why try catch isn't trying and catching?
then pressing F10 it goes to here.. which is part of my ORM wrapper... hmm I wonder if this is the problem.
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (_unitOfWorkScope != null)
{
_unitOfWorkScope.Dispose();
}
base.OnResultExecuted(filterContext);
}
The delegate passed to OrderBy is not invoked until you try to access the elements in the list.
So I think the error is not caught because your collection is not enumerated until the view is being rendered, after the action method has returned.
This is a bad design; you shouldn't have any code in your catch that could potentially throw another exception.
If I'm understanding your code, you want to attempt to parse the RFID to an int, but fall back on string as your sort if a failure?
If you can't gaurentee that the Numbers of the RfidTags won't be a number (which seems a silly naming structure), then I'd leave it as a string sort and ditch the int parsing
The answer was that LightSpeed was failing out. Once the support was added (very quickly - awesome product!) it all worked fine:
// trying to convert to an int.. if fail, use string
// need up to date nightly build of LS3.1 for this to work
// otherwise trycatch will fail due to LS crashing out.
try
{
var orderedListOfRfidTags = uow.RfidTags
.OrderBy(t => Convert.ToInt32(t.Number))
.ToList();
return View(orderedListOfRfidTags);
}
catch
{
var orderedListOfRfidTags = uow.RfidTags
.OrderBy(t => t.Number)
.ToList();
return View(orderedListOfRfidTags);
}
We're migrating an application to use IIS7 integrated mode. In library code that is designed to work either within the context of an HTTP request or not, we commonly have code like this:
if (HttpContext.Current != null &&
HttpContext.Current.Request != null) {
// do something with HttpContext.Current.Request
} else {
// do equivalent thing without HttpContext..
}
But in IIS7 integrated mode the check for HttpContext.Current.Request throws an exception whenever this code is called from Application_Start.
protected void Application_Start(object sender, EventArgs e)
{
SomeLibrary.DoSomethingWithHttpContextCurrentDetection();
}
Results in:
System.Web.HttpException: Request is not available in this context
How can I detect whether the request is really available without wrapping these calls in an exception handler and taking action based on whether an exception is generated or not.
Looking at HttpContext in Reflector I see it has an internal bool HideRequestResponse field but it's internal so I can only get to it with reflection and that's fragile. Is there a more official/approved way to determine if it's ok to call HttpContext.Request?
This blog post about the subject says not to use HttpContext, but how, in generic library code, can you determine if it's ok to use HttpContext?
http://mvolo.com/iis7-integrated-mode-request-is-not-available-in-this-context-exception-in-applicationstart/
I'm using the work-around mentioned there which is to use Application_BeginRequest and an initialized field to only initialize once as part of BeginRequest, but that has to be done in every calling application whereas I'd prefer to make the library code more robust and handle this situation regardless of where it's called from.
I would refactor your code to this:
if (IsRequestAvailable())
{
// do something with HttpContext.Current.Request...
}
else
{
// do equivalent thing without HttpContext...
}
public Boolean IsRequestAvailable()
{
if (HttpContext.Current == null)
return false;
try
{
if (HttpContext.Current.Request == null)
return false;
}
catch (System.Web.HttpException ex)
{
#if DEBUG
// Testing exception to a magic string not the best practice but
// it works for this demo.
if (ex.Message == "Request is not available in this context")
return false;
throw;
#else
return false;
#endif
}
return true;
}
Your question asked not to use exception handling (I assume for performance reasons) and my answer does. However, by changing your code from using "If (HttpContext.Current != null && HttpContext.Current.Request != null)" to "If (IsRequestAvailable())" you only have one place to change the code when you find an answer how not to use exception handling.
I'm afraid the answer is that you can't get what you want - Microsoft sees this case as an 'exceptional circumstance' and so it will throw an exception.
You can use reflection as you describe in your answer but you don't want to and so are limited by the API that Microsoft have provided, for better or for worse.
If you do decide to use reflection, of note is the HttpApplication.InitInternal method which is what sets the HideRequestResponse flag.
Hope that helps. I would suggest you file a report with Microsoft Connect.
You should not even use Request (or Response) in the Application_Start since application could be started without a request. So in the future your application won't even run when other parts of framework stop providing the Request object.
If you want to just hack it temporarily, you could use Reflection (if you have above-medium trust) or catching an exception (even though you don't want to) and store the result in a static variable or possibly use a static HttpContext wrapper:
Also you could use HttpRuntime.UsingIntegratedPipeline.
So the best approach is remove the dependance of your classes on HttpContext when they are being initialized or not initalize them in appstart.
What is your reasoning to use Request in the app start anyway? For statistics? Or just telling the user he woke the application?
Edited with code to explain better:
public static class ContextWrapper
{
public static HttpRequest Request
{
get
{
HttpContext context = HttpContext.Current;
if (context == null) return null;
if (HttpRuntime.UsingIntegratedPipeline)
{
try { return context.Request; }
catch (HttpException e) { /* Consume or log e*/ return null; }
// Do not use message comparison - .NET translates messages for multi-culture environments.
}
return context.Request;
}
}
}
And in code:
if (ContextWrapper.Request != null) //...
Or a user-controlled faster way:
public static class ContextWrapper2
{
public static bool IsIis7IntegratedAppStart { get; set; }
public static HttpRequest Request
{
get
{
if (ContextWrapper2.IsIis7IntegratedAppStart) return null;
HttpContext context = HttpContext.Current;
if (context == null) return null;
return context.Request;
}
}
}
And in app start:
protected void Application_Start(object sender, EventArgs e)
{
yourLibraryNamespace.ContextWrapper2.IsIis7IntegratedAppStart = true;
//...
yourLibraryNamespace.yourClass.Init();
//...
yourLibraryNamespace.ContextWrapper2.IsIis7IntegratedAppStart = false;
}
You could note this behaviour in your documentation and all should be well. AppStart-like context should be the only place where you get such an exception.
You could also implement IDisposable on a member and use it in appStart with the using statement so you do not forget to set IsIis7IntegratedAppStart = false.
I think I have the solution for you. I maintain a logging library and have the same issue as you. If it is a web request I am grabbing some data from the HttpContext. But depending on how the logging library is used this same scenario can happen. So here is my solution. The key fix for me was checking if the Handler was null or not.
if (System.Web.Hosting.HostingEnvironment.IsHosted
&& System.Web.HttpContext.Current != null
&& System.Web.HttpContext.Current.Handler != null
&& System.Web.HttpContext.Current.Request != null)
{
//access the Request object here
}
Depending on what you are trying to accomplish, you may be able to get some of the properties and settings around the web app from System.Web.Hosting.HostingEnvironment
I added a comment, but it gets auto-hidden.
I think it's more important to have an idea of what it is that you need from the request.
For instance, the link you provided which provides a workaround is looking for Request.ApplicationPath.
If that's actually what you're looking for (for, say, loading the web.config vs the app.config), you could do this:
if (HttpRuntime.AppDomainAppId != null)
return WebConfigurationManager.OpenWebConfiguration(HttpRuntime.AppDomainAppVirtualPath);
else
return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
If this (or HttpRuntime.ApplicationPath) isn't what you're actually looking for, it would be helpful to know which properties of the Request you are actually looking for. Maybe there's a better, safer way to get there.