WCF NullReferenceException - asp.net-mvc

I'm hosting an ASP.NET MVC site on Winhost and recently added a WCF data service for users providing feedback. The service works fine from my local machine, but when I deploy it I get the following System.NullReferenceException returned in Fiddler whenever I try to save an entry to the service:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code></code>
<message xml:lang="en-US">An error occurred while processing this request.</message>
<innererror>
<message>Object reference not set to an instance of an object.</message>
<type>System.NullReferenceException</type>
<stacktrace> at System.Data.Services.Providers.ObjectContextServiceProvider.SetValue(Object targetResource, String propertyName, Object propertyValue)
at System.Data.Services.Serializers.Deserializer.SetPropertyValue(ResourceProperty resourceProperty, Object declaringResource, Object propertyValue, ContentFormat contentFormat, IDataService service)
at System.Data.Services.Serializers.PlainXmlDeserializer.ApplyProperty(XmlReader reader, String propertyName, ResourceType resourceType, Object resource)
at System.Data.Services.Serializers.PlainXmlDeserializer.ApplyContent(XmlReader reader, ResourceType resourceType, Object resource)
at System.Data.Services.Serializers.PlainXmlDeserializer.ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, Object resource, EpmAppliedPropertyInfo propertiesApplied, Int32 currentObjectCount)
at System.Data.Services.Serializers.SyndicationDeserializer.ApplyProperties(SyndicationItem item, ResourceType resourceType, EpmAppliedPropertyInfo propertiesApplied, Object resource)
at System.Data.Services.Serializers.SyndicationDeserializer.CreateObject(SegmentInfo segmentInfo, Boolean topLevel, SyndicationItem item)
at System.Data.Services.Serializers.SyndicationDeserializer.CreateSingleObject(SegmentInfo segmentInfo)
at System.Data.Services.Serializers.Deserializer.ReadEntity(RequestDescription requestDescription)
at System.Data.Services.Serializers.Deserializer.HandlePostRequest(RequestDescription requestDescription)
at System.Data.Services.DataService`1.HandlePostOperation(RequestDescription description, IDataService dataService)
at System.Data.Services.DataService`1.ProcessIncomingRequest(RequestDescription description, IDataService dataService)
at System.Data.Services.DataService`1.HandleNonBatchRequest(RequestDescription description)
at System.Data.Services.DataService`1.HandleRequest()</stacktrace>
</innererror>
</error>

Turn on tracing both on the server and on the client (see http://msdn.microsoft.com/en-us/library/ms733025.aspx), then use SvcTraceViewer (http://msdn.microsoft.com/en-us/library/ms732023.aspx). It will usually give you a more detailed exception.

My problem turned out to be 2 issues:
My site reroutes Url's for all GET requests to lower case. ODATA queries are case sensitive. This was causing me trouble with diagnosing the problem but wasn't causing the POST issue. Removing this for my service uri helped me identify the real problem.
The real issue was that my DataContext for my POCO entities had proxy generation enabled.
Here's a lengthier description of how I found the problem in case it helps anyone debug a similar issue:
Per Dan's suggestion, I enabled tracing to see if I could get any additional details. This showed me that I was getting a System.ServiceModel.CommunicationObjectAbortedException. I searched for the cause of this for a while with no success.
Next, I set my EntitySetRights for my DataService to EntitySetRights.All to see if I could determine the error by attempting to read my entity set (note that in my case this is a temporary change for debugging).
static public void InitializeService(DataServiceConfiguration config) {
...
config.SetEntitySetAccessRule("myentityset", EntitySetRights.All);
...
}
I then queried the service http://mydomain.com/myservice.svc/myentityset and received the following error:
Resource not found for the segment 'myentityset'
This turned out to be due to my site forcing all urls to lower case (apparently ODATA queries are case sensitive). My entity set is named something like 'MyEntitySet', but it was being queried as 'myentityset' Once I disabled this for my service url, I received an error similar to the following:
Internal Server Error. The type 'System.Data.Entity.DynamicProxies.myentity_XXXX' is not a complex type or an entity type
Looking up this error led me to this link identifying my core problem. The problem is with POCO Entity Generation for DataServices. In order to fix the problem ProxyCreationEnabled needs to be set to false. I added the following method to my T4 template that generates my ObjectContext.
<#+
private void WriteProxyCreation()
{
#>
this.ContextOptions.ProxyCreationEnabled = false;
<#+
}
#>
I then added a call to my method in each of the constructors similar to the following:
public <#=code.Escape(container)#>()
: base(ConnectionString, ContainerName)
{
<#
WriteLazyLoadingEnabled(container);
WriteProxyCreation();
#>
}

Related

#Inject into Jax-rs resource: CWWAM0002E: An exception occurred while merging an annotation into deployment descriptor:

I am getting a weird exception when I deploy Rest sevice locally to my WAS 85 environment in eclipse:
CWWAM0002E: An exception occurred while merging an annotation into deployment descriptor: com.ibm.wsspi.amm.merge.MergeException: Unable to find EnterpriseBean for class WackyDoodleResource
com.ibm.wsspi.amm.merge.MergeException: Unable to find EnterpriseBean for class WackyDoodleResource
This is not my real code but here is how I set it up with names changed to protect the innocent:
#Path("/wacky-doodle-resource")
public class WackyDoodleResource{
#Context UriInfo uriInfo
#Context SecurityContext securityContext;
#Inject WackyDoodleEJB wackyDoodleEJB;
#POST
#Consumes(MediaType.APPLICATIONI_JSON)
#RolesAllowed("WACKYDOODLES")
#Produces(MediaType.APPLICATIONI_JSON)
public Response createWackyDoodle(WackyDoodleRequestRO requestRO{
String response = null;
response = wackyDoodleEJB.createWackyDoodle(requestRO)
}
return Response.ok(response)).build();
}
#Default
#Singleton
public class WackyDoodleEJB implements IWackyDoodleEJB{
public String createWackyDoodle(WackyDoodleRequestRO req){
System.out.println("Do Something Wacky!");
}
}
public interface IWackyDoodleEJB{
public String createWackyDoodle(WackyDoodleRequestRO request);
}
(Simple recreation of my more complex code for illustration purposes)
I see that exception when I deploy my ear to my local Websphere server. The application appears to start up and deploy just fine (if you don't pay attention to what you find in the logs). However, when I attempt to hit any of my http request #myResources, I get this oddly nondescript message
E com.ibm.ws.webcontainer.internal.WebContainer handleRequest SRVE0255E: A WebGroup/Virtual Host to handle / has not been defined.
I suspect it has something to do with my ear not publishing correctly (the exception in my question). I honestly do not know however. So, what could be happening here? This seems like it should be pretty boilertplate stuff?
The error suggests that I should Turn my regular resource pojo into an EJB? If I add, for example, the stateless #nnotation to my class, the above exception in the logs goes away, but I am still not able to hit my sevice resources. I get the same nondescript exception. I am at a loss and I have been looking at this for an hour. If you could point me in any direction I would appreciate it.

The anti-forgery token could not be decrypted

I have a form:
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()...
and action:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl, string City)
{
}
occasionally (once a week), I get the error:
The anti-forgery token could not be decrypted. If this application is
hosted by a Web Farm or cluster, ensure that all machines are running
the same version of ASP.NET Web Pages and that the configuration
specifies explicit encryption and validation keys. AutoGenerate cannot
be used in a cluster.
i try add to webconfig:
<machineKey validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps" />
but the error still appears occasionally
I noticed this error occurs, for example when a person came from one computer and then trying another computer
Or sometimes an auto value set with incorrect data type like bool to integer to the form field by any jQuery code please also check it.
I just received this error as well and, in my case, it was caused by the anti-forgery token being applied twice in the same form. The second instance was coming from a partial view so wasn't immediately obvious.
validationKey="AutoGenerate"
This tells ASP.NET to generate a new encryption key for use in encrypting things like authentication tickets and antiforgery tokens every time the application starts up. If you received a request that used a different key (prior to a restart for instance) to encrypt items of the request (e.g. authenication cookies) that this exception can occur.
If you move away from "AutoGenerate" and specify it (the encryption key) specifically, requests that depend on that key to be decrypted correctly and validation will work from app restart to restart. For example:
<machineKey
validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7
AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"
decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation="SHA1"
decryption="AES"
/>
You can read to your heart's content at MSDN page: How To: Configure MachineKey in ASP.NET
Just generate <machineKey .../> tag from a link for your framework version and insert into <system.web><system.web/> in Web.config if it does not exist.
Hope this helps.
If you get here from google for your own developer machine showing this error, try to clear cookies in the browser. Clear Browser cookies worked for me.
in asp.net Core you should set Data Protection system.I test in Asp.Net Core 2.1 or higher.
there are multi way to do this and you can find more information at Configure Data Protection and Replace the ASP.NET machineKey in ASP.NET Core and key storage providers.
first way: Local file (easy implementation)
startup.cs content:
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
{
Configuration = configuration;
WebHostEnvironment = webHostEnvironment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment WebHostEnvironment { get; }
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// .... Add your services like :
// services.AddControllersWithViews();
// services.AddRazorPages();
// ----- finally Add this DataProtection -----
var keysFolder = Path.Combine(WebHostEnvironment.ContentRootPath, "temp-keys");
services.AddDataProtection()
.SetApplicationName("Your_Project_Name")
.PersistKeysToFileSystem(new DirectoryInfo(keysFolder))
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}
}
second way: save to db
The Microsoft.AspNetCore.DataProtection.EntityFrameworkCore NuGet
package must be added to the project file
Add MyKeysConnection ConnectionString to your projects
ConnectionStrings in appsettings.json > ConnectionStrings >
MyKeysConnection.
Add MyKeysContext class to your project.
MyKeysContext.cs content:
public class MyKeysContext : DbContext, IDataProtectionKeyContext
{
// A recommended constructor overload when using EF Core
// with dependency injection.
public MyKeysContext(DbContextOptions<MyKeysContext> options)
: base(options) { }
// This maps to the table that stores keys.
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
startup.cs content:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// ----- Add this DataProtection -----
// Add a DbContext to store your Database Keys
services.AddDbContext<MyKeysContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyKeysConnection")));
// using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.PersistKeysToDbContext<MyKeysContext>();
// .... Add your services like :
// services.AddControllersWithViews();
// services.AddRazorPages();
}
}
If you use Kubernetes and have more than one pod for your app this will most likely cause the request validation to fail because the pod that generates the RequestValidationToken is not necessarily the pod that will validate the token when POSTing back to your application. The fix should be to configure your nginx-controller or whatever ingress resource you are using and tell it to load balance so that each client uses one pod for all communication.
Update: I managed to fix it by adding the following annotations to my ingress:
https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/
Name Description Values
nginx.ingress.kubernetes.io/affinity Sets the affinity type string (in NGINX only cookie is possible
nginx.ingress.kubernetes.io/session-cookie-name Name of the cookie that will be used string (default to INGRESSCOOKIE)
nginx.ingress.kubernetes.io/session-cookie-hash Type of hash that will be used in cookie value sha1/md5/index
I ran into this issue in an area of code where I had a view calling a partial view, however, instead of returning a partial view, I was returning a view.
I changed:
return View(index);
to
return PartialView(index);
in my control and that fixed my problem.
I got this error on .NET Core 2.1. I fixed it by adding the Data Protection service in Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection();
....
}
you are calling more than one the #Html.AntiForgeryToken() in your view
I get this error when the page is old ('stale'). A refresh of the token via a page reload resolves my problem. There seems to be some timeout period.
I found a very interesting workaround for this problem, at least in my case. My view was dynamically loading partial views with forms in a div using ajax, all within another form. the master form submits no problem, and one of the partials works but the other doesn't. The ONLY difference between the partial views was at the end of the one that was working was an empty script tag
<script type="text/javascript">
</script>
I removed it and sure enough I got the error. I added an empty script tag to the other partial view and dog gone it, it works! I know it's not the cleanest... but as far as speed and overhead goes...
I know I'm a little late to the party, but I wanted to add another possible solution to this issue. I ran into the same problem on an MVC application I had. The code did not change for the better part of a year and all of the sudden we started receiving these kinds of error messages from the application.
We didn't have multiple instances of the anti-forgery token being applied to the view twice.
We had the machine key set at the global level to Autogenerate because of STIG requirements.
It was exasperating until I got part of the answer here: https://stackoverflow.com/a/2207535/195350:
If your MachineKey is set to AutoGenerate, then your verification
tokens, etc won't survive an application restart - ASP.NET will
generate a new key when it starts up, and then won't be able to
decrypt the tokens correctly.
The issue was that the private memory limit of the application pool was being exceeded. This caused a recycle and, therefore, invalidated the keys for the tokens included in the form. Increasing the private memory limit for the application pool appears to have resolved the issue.
My fix for this was to get the cookie and token values like this:
AntiForgery.GetTokens(null, out var cookieToken, out var formToken);
For those getting this error on Google AppEngine or Google Cloud Run, you'll need to configure your ASP.NET Core website's Data Protection.
The documentation from the Google team is easy to follow and works.
https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider
A general overview from the Microsoft docs can be found here:
https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider
Note that you may also find you're having to login over and over, and other quirky stuff going on. This is all because Google Cloud doesn't do sticky sessions like Azure does and you're actually hitting different instances with each request.
Other errors logged, include:
Identity.Application was not authenticated. Failure message: Unprotect ticket failed

WebSecurity.InitializeDatabaseConnection method can be called only once

I'm trying Windows Azure to host an MVC4 web application.
I've created a test app, using VS2012 MVC4 internet application template and added a custom Model and Controller to it.
I've published it on Azure and managed to get 'update-database' apply migrations to the Azure Database.
When i try the app locally, but using the Azure SQL database, it works fine.
I can login/register and use my test controller.
When i try the app online, i can use the test controller but login or register links give the following exception:
Server Error in '/' Application.
The "WebSecurity.InitializeDatabaseConnection" method can be called only once.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The "WebSecurity.InitializeDatabaseConnection" method can be called only once.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The "WebSecurity.InitializeDatabaseConnection" method can be called only once.]
WebMatrix.WebData.WebSecurity.InitializeMembershipProvider(SimpleMembershipProvider simpleMembership, DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean createTables) +123
WebMatrix.WebData.WebSecurity.InitializeProviders(DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables) +51
WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection(String connectionStringName, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables) +52
MembershipTest2.Filters.SimpleMembershipInitializer..ctor() +193
Do you have any idea where that comes from ?
If i debug (the local version), this method is only called once.
Thanks.
You could try encapsulating the call(s) to that method to ensure it's not called more then once
if (!WebMatrix.WebData.WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection(...);
}
in my case I had both
(in web.config)
<add key="enableSimpleMembership" value="true" />
and
(in _ViewStart.cshtml)
WebSecurity.InitializeDatabaseConnection("club", "Account", "UserID", "UserName", autoCreateTables: true);
Solution: it seems you cannot have both, so remove one
Does the following SO discussion help you?
Cannot seed Users & Roles
I did find the following article helped me lot to use newer MVC4 & EF together with Simple Membership Provider so if you haven't read it please take a look:
SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates

Upgrading to MVC4 RC: No MediaTypeFormatter is available to read an object of type 'TestRequestModel' from content with media type ''undefined''

I've been using the MVC4 beta and am currently working to upgrade to the recently released RC version.
It appears that model-binding complex request types has changed, but I can't figure out how / what I'm doing wrong.
For example, say I have the following API controller:
public class HomeApiController : ApiController
{
public TestModel Get()
{
return new TestModel
{
Id = int.MaxValue,
Description = "TestDescription",
Time = DateTime.Now
};
}
}
This yields the expected result:
<TestModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/xxxx">
<Description>TestDescription</Description>
<Id>2147483647</Id>
<Time>2012-06-07T10:30:01.459147-04:00</Time>
</TestModel>
Now say I just change the signature, taking in a request type, like this:
public TestModel Get(TestRequestModel request)
{
...
public class TestRequestModel
{
public int? SomeParameter { get; set; }
}
I now get the following error:
<Exception xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/System.Web.Http.Dispatcher">
<ExceptionType>System.InvalidOperationException</ExceptionType>
<Message>
No MediaTypeFormatter is available to read an object of type 'TestRequestModel' from content with media type ''undefined''.
</Message>
<StackTrace>
at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)
</StackTrace>
</Exception>
I've looked at the source code of where this exception is thrown in the HttpContentExtensions, but it looks like it checks for content headers (which I should have), and if it doesn't have that it tries to get a formatter from the MediaTypeFormatter collection it has for the specific type (which it can't) and then throws.
Anyone else experienced this? Some global registration I'm missing?
I see your original question was answered, but to answer the other one, Model binding has changed somewhat in the RC.
http://weblogs.thinktecture.com/cweyer/2012/06/aspnet-web-api-changes-from-beta-to-rc.html
This link has some details about it. But to sum up the change that appears to be affecting you, Model binding pulls its values from either the body, or the uri of the request. This is true for previous releases as well, but with the release candidate, MVC4 will, by default, look to the body for complex types, and the uri for value types.
So, if you submit a body with your request containing the "SomeParameter" key, you should see it bind. Or you could bind with the url if you change the declaration to:
public TestModel Get(int? someParameter)
{
}
Thankfully, the team foresaw the potential problems with this and left us with attributes we could use to override this behavior.
public TestModel Get([FromUri]TestRequestModel request)
{
}
The key here is the [FromUri] which tells the model binder to look in the uri for the values. There is also [FromBody] if you want to put a value type in the body of a request.
We were seeing the same thing. In our case the problem was a complex object being passed into a get method. We needed to add a [FromUri] attribute in the parameter to that method.
http://forums.asp.net/t/1809925.aspx/1?GET+requests+with+complex+object+as+input+parameter
public class SearchController : ApiController
{
// added [FromUri] in beta to RC transition otherwise media type formatter error
public IQueryable<SearchResultEventModel> Get( [FromUri]SearchSpecModel search )
{
// ...
}
}

ASP.Net MVC, JS injection and System.ArgumentException - Illegal Characters in path

In my ASP.Net MVC application, I use custom error handling.
I want to perform custom actions for each error case I meet in my application.
So I override Application_Error, get the Server.GetLastError();
and do my business depending on the exception, the current user, the current URL (the application runs on many domains), the user IP, and many others.
Obviousely, the application is often the target of hackers.
In almost all the case it's not a problem to detect and manage it, but for some JS URL attacks, my error handling does not perform what I want it to do.
Ex (from logs) :
http://localhost:1809/Scripts/]||!o.support.htmlSerialize&&[1
When I got such an URL, an exception is raised when accessing the ConnectionStrings section in the web.config, and I can't even redirect to another URL.
It leads to a "System.ArgumentException - Illegal Characters in path, etc."
The screenshot below shows the problem :
http://screencast.com/t/Y2I1YWU4
An obvious solution is to write a HTTP module to filter the urls before they reach my application, but I'd like to avoid it because :
I like having the whole security being managed in one place (in the Application_Error() method)
In the module I cannot access the whole data I have in the application itself (application specific data I don't want to debate here)
Questions :
Did you meet this problem ?
How did you manage it ?
Thanks for you suggestions,
Mose
PS : here is the stack trace :
System.ArgumentException: Illegal characters in path.
at System.IO.Path.CheckInvalidPathChars(String path)
at System.IO.Path.Combine(String path1, String path2)
at System.Web.Configuration.UserMapPath.GetPhysicalPathForPath(String path, VirtualDirectoryMapping mapping)
at System.Web.Configuration.UserMapPath.GetPathConfigFilename(String siteID, VirtualPath path, String& directory, String& baseName)
at System.Web.Configuration.UserMapPath.MapPath(String siteID, String path)
at System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull)
at System.Web.Hosting.HostingEnvironment.MapPathInternal(VirtualPath virtualPath, Boolean permitNull)
at System.Web.CachedPathData.GetPhysicalPath(VirtualPath virtualPath)
at System.Web.CachedPathData.GetConfigPathData(String configPath)
at System.Web.CachedPathData.GetVirtualPathData(VirtualPath virtualPath, Boolean permitPathsOutsideApp)
at System.Web.HttpContext.GetFilePathData()
at System.Web.HttpContext.GetConfigurationPathData()
at System.Web.Configuration.RuntimeConfig.GetConfig(HttpContext context)
at System.Web.HttpContext.get_ImpersonationToken()
at System.Web.ClientImpersonationContext.Start(HttpContext context, Boolean throwOnError)
at System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(Exception error)

Resources