A problem with "Add Service Reference", and actually with SvcUtil over all its features.
In order to reproduce you just need to add an OperationContract with argument or returning the following class :
[XmlSchemaProvider("MySchema")]
public class MyStructure : IXmlSerializable
{
private XmlElement e;
private static void Func(object o, ValidationEventArgs args)
{
}
public static XmlQualifiedName MySchema(XmlSchemaSet xs)
{
//xs.XmlResolver = new XmlUrlResolver();
XmlSchema s = XmlSchema.Read(new XmlTextReader(new StringReader("<?xml version=\"1.0\"?><xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><xs:complexType name=\"MyStructure\"><xs:sequence><xs:any /></xs:sequence></xs:complexType></xs:schema>")), null);
xs.Add(s);
return new XmlQualifiedName("MyStructure");
}
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
XmlDocument doc = new XmlDocument();
e = (XmlElement)doc.ReadNode(reader);
}
public void WriteXml(XmlWriter writer)
{
e.WriteTo(writer);
}
#endregion
}
The result is that when you use AddWebReference or AddSerivceReference without a reference to the class library containing the MyStructure type, everything will be fine ad you will get an xmlElement representation at the auto created proxy.
However, when you have a reference you will get the following warning :
================
Warning 1 Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Referenced type 'ServiceLibrary.MyStructure, ServiceLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' with data contract name 'MyStructure' in namespace '' cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types.
XPath to Error Source: //wsdl:definitions[#targetNamespace='http://tempuri.org/']/wsdl:portType[#name='IService1'] \Projects\WCFSample\WCFExample\TestAddReference\Service References\ServiceReference1\Reference.svcmap 1 1 TestAddReference
======================
And no proxy will be generated for you.
Now, the internet is full with descriptions of this when you have a generic DataContract, and/or using IsReference attribute.
This is a much serious problem, since any non-typed data will do this problem.
Could not find any way to solve the problem. What if I want to know the type at the client side, by sharing the class library of the contracts ?
This type of exception generally means there is at least one difference in the type contracts generated by the service as compared to the referenced types (as the message indicates!). But it may not be obvious at first glance, as I found out. Make sure all nested and referenced types are up to date with the server. In my case, nested types were updated on the server. I thought I had updated by locally referenced assembly (and the shared reference types) but I missed some. It took close examination to find the culprit.
See additional information in this question
I have a suggestion:
I had similar errors, including:
the .svcmap file cannot be found. It may have been moved or deleted. To generate a new .svcmap file, delete the service reference and add it again.
And at that point, no way to delete the service reference unless I close VS2010 and open it again.
The situation is: my WCF service is running, I programmatically added a Description.ServiceMetadataBehavior at an HTTP address that I define.
In VS2010, I try to add a service reference at the HTTP address, I see my service, I add the reference, and voila, errors and warning.
The problem: my HTTP address is containing some key words that WCF doesn't like. Specifically the word COM (it breaks with LPT too).
So my solution: modify my HTTP address not to have the word COM. It worked for me.
If the service is hosted over HTTPS, go into the server's IIS Manager. Under "SSL Settings" for the site, make sure "Require SSL" is checked, and check the Client Certificates radio button for "Accept".
Related
I can't seem to find an example of generating proxies from WSDLs with shared types but without having any XSDs to go along with them. Can anyone please mark this as duplicate and point me to an example please?
Here are 2 services, each has its own namespace and a common type. The only thing that is publicly accessible are their WSDLs, there is no type's XSD or its .dll to pass to wsdl.exe /sharedtypes or svcutils and without it I end up with identical class Foo that I can't pass in to SetFoo and class Foo1.
The best I could come up with is generating proxies programmatically and detecting duplicates via CodeDOM, ignoring DataContract/WebServiceBinding namespaces, but it's a huge mess...
[WebService(Namespace = "http://tempuri.org/FOO1")]
public class Service1 : WebService
{
[WebMethod]
public Foo GetFoo()
{
return new Foo();
}
}
[WebService(Namespace = "http://tempuri.org/FOO2")]
public class Service2 : WebService
{
[WebMethod]
public void SetFoo(Foo foo)
{
}
}
public class Foo
{
public int Bar { get; set; }
}
There is a way of doing this, which is outlined here.
In your case you can skip the first step, generate the proxy from service 1 and then use the /r flag on svcutil to reference the service 1 proxy assembly when you generate your service 2 proxy.
This will ensure your service 2 proxy will use the same instance of Foo from your service 1 proxy.
However, have you considered just hosting a single service with two operations? It would save you a lot of work.
Edit: Also have a look at this post:
http://blogs.msdn.com/b/youssefm/archive/2009/10/09/reusing-types-in-referenced-assemblies-with-svcutil-s-r-switch.aspx
First off, you need to set the [DataContract(Namespace="some namespace here")] for all common service data types, otherwise when the WSDL and XSDs are generated then you will have objects from two difference namespace --- this is absolutely essential. The namespace value will only apply to the types defined in the XSD and not in the WSDL. XSD = data, WSDL = service.
The XSDs and WSDL and generated if, and only if, you have the META service behavior set - add this behavior and then you can navigate to the URL. The URL of the META service behavior will then have a link to your WSDLs and XSDs.
I use the following piece of code to self-host services in windows services rather than through IIS, however the same principals apply....
/// <summary>
/// Enables meta data output for a service host.
/// </summary>
/// <param name="host">The service host.</param>
/// <remarks>Must be invoked prior to starting the service host.</remarks>
public static void SetupMetaDataBehaviour(ServiceHost host)
{
ServiceMetadataBehavior metaDataBehaviour = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metaDataBehaviour == null)
{
metaDataBehaviour = new ServiceMetadataBehavior();
metaDataBehaviour.HttpGetEnabled = true;
host.Description.Behaviors.Add(metaDataBehaviour);
}
else
{
metaDataBehaviour.HttpGetEnabled = true;
}
}
after adding your two web references:
double click on the second web service reference
in the object browser navigate to the definition of Foo
right click on Foo and choose go to definition
delete the definition for the class Foo
add a using statement for the namespace of webservice one
find and replace all instances of <namespace-of-service-reference-2>.Foo with just Foo
This should fix your problem as it forces the autogenerated code for both service references to use the same class declaration.
I have a windows service that references an assembly which contains the following class.
[Serializable]
public class User
{
public User(string userName)
{
UserName = userName;
}
public string UserName { get; private set; }
}
This service has a method to allow us to create a User:
public User CreateUser(User user)
{
//Create and return user
}
Through remoting we are able to call this method in the service that takes in User object from our application. The application references the same assembly that the service does for the User class but it forces a specific 1.0.0.0 version.
CreateUser(User user);
We would like to change the existing assembly that is referenced from each project to add a new property "Phone" to the User class.
[Serializable]
public class User
{
public User(string userName)
{
UserName = userName;
}
public string UserName { get; private set; }
**public string Phone { get; set; }**
}
We will increment the assembly version from 1.0.0.0 to 2.0.0.0. The windows service will have a reference to the 2.0.0.0 version of the assembly in the GAC. Because some of our clients are slow at upgrading and they force specific versions of the assembly or copy it local they will still be referencing the 1.0.0.0 version.
With this change to the service assembly reference the marshaller that deserializes/serializes the object from the service to the application throws a serialization error. "The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter..."
The change we made should be a non breaking change since we just added additional feature. Is there a way to allow the existing application continue and use the 1.0.0.0 version of the assembly and serialize the 2.0.0.0 without the new property down to them without some convoluted conversion on the service?
UPDATE:
We are using the following to connect over to our service
marshaller = ChannelFactory<T>.CreateChannel(new NetTcpBinding() { MaxReceivedMessageSize = MaxResponseSize }, new EndpointAddress(new Uri(new Uri(servers[serverIndex]), serviceName)));
Inner exception:
http://tempuri.org/:CreateUserResult. The InnerException message was ''EndElement' 'CreateUserResult' from namespace 'http://tempuri.org/' is not expected. Expecting element '_someOtherField'.'. Please see InnerException for more details
...Next inner is null
As I suspected, here's the problem;
NetTcpBinding
(from your edit). Basically, WCF includes some nice friendly contract-based support, and some less-than-friendly type-based support.
If at all possible, I would suggest the simplest option here is to not use NetTcp as it by default uses NetDataContractSerializer (type-based), so will have versioning issues. Alternatively, you can use oter serializers on the transport - for example DataContractSerializer of protobuf-net. However, changing this would itself be a breaking change.
I gather it is possible to use a custom binder with NetDataContractSerializer - see Problem deserializing with NetDataContractSerializer after refactoring code . If you can get that working it should preserve the API, but it should not be underestimated; I think that will be a maintenance burden, in all honesty. I'd rather cut my losses, break the API once and switch to a contract-based serializer.
Maybe the OptionalField attribute works for you, depending on the formatter, see http://msdn.microsoft.com/en-us/library/system.runtime.serialization.optionalfieldattribute.aspx.
Okay. This is my company's customer portal, it's an MVC 2 project. We have a back end SAP system that the portal draws data from. But it does not directly hit SAP, it sends an xml request to a VB app that gets the data and sends it back in an xml response. There is an interface IRequest that all the various requests implement examples would be CustomerNumberRequest, CompanyNameRequest, etc. These all implement the method ToXml which as the name suggests simply builds xml to send. All of the existing requests work fine. (Let me preface this by saying that I inherited this project and the guy who wrote it is no longer with us) I am now trying to send a request to get the Rep Groups from SAP. I basically copied one of the other requests verbatim, making the necessary tweaks to send the appropriate request. But it keeps failing with error messages that I don't understand:
The formatter threw an exception while
trying to deserialize the message:
There was an error while trying to
deserialize parameter
http://tempuri.org/:request. The
InnerException message was 'The
deserializer cannot load the type to
deserialize because type
'XXXXX.CustomerPortal.Domain.RepGroupRequest'
could not be found in assembly
'XXXXX.CustomerPortal.Domain,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'. Check that the
type being serialized has the same
contract as the type being
deserialized and the same assembly is
used.'. Please see InnerException for
more details.
This error happens right at _communicationService.ProcessRequest(request); (shown below) It does not enter the ProcessRequest method it just tries to create a NetDataContractSerializer here:
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new NetDataContractSerializer();
}
and then it dies. These are the methods being called:
private void PopulateRepGroups()
{
List<string> repGroups = new List<string>();
RepGroupRequest request = new RepGroupRequest();
foreach (RepGroup repGroup in _repService.GetRepGroups(request))
repGroups.Add(repGroup.RepGroupName);
ViewData["RepGroups"] = new SelectList(repGroups);
}
public List<RepGroup> GetRepGroups(RepGroupRequest request)
{
string response = _communicationService.ProcessRequest(request);
return RepGroupResponseFactory.GetRepGroupResponse(response);
}
Can anybody tell me what this error message is telling me? It says the type cannot be found but the type should be IRequest (that's what it says when the CreateSerializer is hit) which is used all over this. I'm clearly lost, please help!
Quoting your exception
Check that the type being serialized has the same contract as the type being deserialized and the same assembly is used
Check the version of the library on both ends that CustomerPortal.Domain.RepGroupRequest resides in to make sure they are the same version exactly.
I'm writing an application which needs to host several WCF services. One of the strengths of WCF is the ability to configure services without having to recompile, by specifying settings in the app.config file.
When self-hosting, there does not appear to be an out-of-the-box way to automatically host services which are in the app.config file. I found this question which mentions a possible solution of dynamically enumerating services listed in app.config at runtime, and creating a ServiceHost for each.
However, my services, contracts, and the hosting application are all in different assemblies. This causes Type.GetType(string name) to fails to locate my service type (returns null) because it is defined in a different assembly.
How can I reliably host all services listed in the app.config file dynamically (i.e., without hard-coding new ServiceHost(typeof(MyService)) in my self-hosting application?
Note: My app.config was generated using the "WCF Configuration Editor" in Visual Studio 2010.
Note also: My primary goal is to have this driven by the app.config file so there is a single point of configuration. I don't want to have to configure this in a separate location.
EDIT: I am able to read the app.config file (see here), but need to be able to resolve types in different assemblies.
EDIT: One of the answers below prompted me to try specifying the AssemblyQualifiedName in app.config instead of just the basic type name. This was able to get around the Type.GetType() problem, however ServiceHost.Open() now fails with an InvalidOperationException regardless of how I attain the type:
// Fails
string typeName = typeof(MyService).AssemblyQualifiedName;
Type myType = Type.GetType(typeName);
ServiceHost host = new ServiceHost(myType);
host.Open(); // throws InvalidOperationException
// Also fails
Type myType2 = typeof(MyService);
ServiceHost host2 = new ServiceHost(myType2);
host2.Open(); // throws InvalidOperationException
Exception details:
Service 'SO.Example.MyService' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
I guess WCF attempts to match the literal string for the service name when parsing the app.config file internally.
EDIT/ANSWER: What I ended up doing was basically what was in the answer below. Instead of using Type.GetType() I know that all of my services are in the same assembly, so I switched to:
// Get a reference to the assembly which contain all of the service implementations.
Assembly implementationAssembly = Assembly.GetAssembly(typeof(MyService));
...
// When loading the type for the service, load it from the implementing assembly.
Type implementation = implementationAssembly.GetType(serviceElement.Name);
// get the <system.serviceModel> / <services> config section
ServicesSection services = ConfigurationManager.GetSection("system.serviceModel/services") as ServicesSection;
// get all classs
var allTypes = AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(s => s.GetTypes()).Where(t => t.IsClass == true);
// enumerate over each <service> node
foreach (ServiceElement service in services.Services)
{
Type serviceType = allTypes.SingleOrDefault(t => t.FullName == service.Name);
if (serviceType == null)
{
continue;
}
ServiceHost serviceHost = new ServiceHost(serviceType);
serviceHost.Open();
}
Based on the other answers, I extended the code to the following, which searches all assemblies for the services in the app.config
That should definitely be possible ! Check out this code fragment - use it as a foundation and go from here:
using System.Configuration; // don't forget to add a reference to this assembly!
// get the <system.serviceModel> / <services> config section
ServicesSection services = ConfigurationManager.GetSection("system.serviceModel/services") as ServicesSection;
// enumerate over each <service> node
foreach(ServiceElement aService in services.Services)
{
Console.WriteLine();
Console.WriteLine("Name: {0} / Behavior: {1}", aService.Name, aService.BehaviorConfiguration);
// enumerate over all endpoints for that service
foreach (ServiceEndpointElement see in aService.Endpoints)
{
Console.WriteLine("\tEndpoint: Address = {0} / Binding = {1} / Contract = {2}", see.Address, see.Binding, see.Contract);
}
}
This right now just prints out the info - but you could definitely use this to actually build up your service hosts inside your own NT service !
Update: ok, sorry, I missed your most important point - the fact the actual services are in different assemblies.
In that case, you need to dynamically load those assemblies, as needed - you could e.g. "just simply know" what assemblies to load, or you could put them all into a specific subdirectories and load all assemblies in that directory, or you could just inspect all assemblies in the same location where your MyOwnServiceHost.exe resides and check if you find any types that you need.
This part - which service type to find in which assembly - isn't handled by WCF configuration - you need to do this yourself, by whichever means makes most sense to you.
// find currently executing assembly
Assembly curr = Assembly.GetExecutingAssembly();
// get the directory where this app is running in
string currentLocation = Path.GetDirectoryName(curr.Location);
// find all assemblies inside that directory
string[] assemblies = Directory.GetFiles(currentLocation, "*.dll");
// enumerate over those assemblies
foreach (string assemblyName in assemblies)
{
// load assembly just for inspection
Assembly assemblyToInspect = Assembly.ReflectionOnlyLoadFrom(assemblyName);
if (assemblyToInspect != null)
{
// find all types
Type[] types = assemblyToInspect.GetTypes();
// enumerate types and determine if this assembly contains any types of interest
// you could e.g. put a "marker" interface on those (service implementation)
// types of interest, or you could use a specific naming convention (all types
// like "SomeThingOrAnotherService" - ending in "Service" - are your services)
// or some kind of a lookup table (e.g. the list of types you need to find from
// parsing the app.config file)
foreach(Type ty in types)
{
// do something here
}
}
}
You correctly identified the answer to your problem in your question link and #marc_s answer also gives the correct approach too. The actual issue you are having is that you need to dynamically get the Type instance of an assembly that may only be referenced through a config file so it may not be loaded into the current AppDomain.
Look at this blog post for a way to dynamically reference assemblies in your code. Although the post is specifically for an ASP.NET application, the general approach should work in a self hosted scenario. The ideas is to replace the Type.GetType(string) call with a private method call that dynamically loads the requested assembly (if needed) and returns the Type object. The parameter you send this method will still be the element.Name and you'll need to figure out which is the correct assembly to load. A simple convention-based assembly naming scheme should work. For example, if service type is:
MyNamespace.MyService.MyServiceImpl
then assume the assembly is:
MyNamespace.MyService
I have a web part that I've developed, and if I manually install the web part it is fine.
However when I have packaged the web part following the instructions on this web site as a guide:
http://www.theartofsharepoint.com/2007/05/how-to-build-solution-pack-wsp.html
I get this error in the log files:
09/23/2008 14:13:03.67 w3wp.exe (0x1B5C) 0x1534 Windows SharePoint Services Web Parts 8l4d Monitorable Error importing WebPart. Cannot import Project Filter.
09/23/2008 14:13:03.67 w3wp.exe (0x1B5C) 0x1534 Windows SharePoint Services Web Parts 89ku High Failed to add webpart http%253A%252F%252Fuk64p12%252FPWA%252F%255Fcatalogs%252Fwp%252FProjectFilter%252Ewebpart;Project%2520Filter. Exception Microsoft.SharePoint.WebPartPages.WebPartPageUserException: Cannot import Project Filter. at Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(Boolean clearConnections) at Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(SPWebPartManager manager, XmlReader reader, Boolean clearConnections, Uri webPartPageUri, SPWeb spWeb) at Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(SPWebPartManager manager, XmlReader reader, Boolean clearConnections, SPWeb spWeb) at Microsoft.SharePoint.WebPartPages.WebPartQuickAdd.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(...
09/23/2008 14:13:03.67* w3wp.exe (0x1B5C) 0x1534 Windows SharePoint Services Web Parts 89ku High ...String eventArgument)
The pertinent bit is:
http%253A%252F%252Fuk64p12%252FPWA%252F%255Fcatalogs%252Fwp%252FProjectFilter%252Ewebpart;Project%2520Filter.
Exception Microsoft.SharePoint.WebPartPages.WebPartPageUserException: Cannot import Project Filter.
at Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(Boolean clearConnections)
at Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(SPWebPartManager manager, XmlReader reader, Boolean clearConnections, Uri webPartPageUri, SPWeb spWeb)
at Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(SPWebPartManager manager, XmlReader reader, Boolean clearConnections, SPWeb spWeb)
at Microsoft.SharePoint.WebPartPages.WebPartQuickAdd.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
And that's accompanied by a rather terse error message: "Cannot import web part".
I have checked and my .dll is registered as safe, it is in the GAC, the feature is activated, and the web parts appear in the web part library with all of the correct properties showing that the webpart files were read successfully.
Everything appears to be in place, yet I get that error and little explanation from SharePoint of how to resolve it.
Any help finding a solution is appreciated.
Figured it out.
The error message is the one from the .webpart file:
<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<!--
The following Guid is used as a reference to the web part class,
and it will be automatically replaced with actual type name at deployment time.
-->
<type name="7F8C4D34-6311-4f22-87B4-A221FA8735BA" />
<importErrorMessage>Cannot import Project Filter.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Project Filter</property>
<property name="Description" type="string">Provides a list of Projects that can be used to Filter other Web Parts.</property>
</properties>
</data>
</webPart>
</webParts>
The problem is that the original .webpart file was created on a 32-bit system with Visual Studio Extensions for WSS installed.
However as I'm now on a 64-bit machine VSEWSS is unavailable, and I believe that results in the above GUID not being substituted as I am not using those deployment tools.
Replacing the GUID with the full type name works.
So if you encounter the error message from your importErrorMessage node, then check that your type node in the .webpart file looks more like this (unrelated example):
<type name="TitleWP.TitleWP, TitleWP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" />
This is in the format:
Class, Namespace, Version, Culture, PublicKey
You can grab that easily from the web.config file associated with your SharePoint instance, as it will be in the safe controls list.
We had this same problem and found that the constructor of our web part was being called by the WebPartImporter and within the constructor we were doing SPSecurity.RunWithElevatedPrivileges.
For some reason the WebPartImporter cannot handle this. So, we simply moved our code out of the constructor to OnInit (where it really belonged) and all is well.
All great suggestions. My problem was unique and silly: I had deployed the solution to the first Web Application but not to the second. SharePoint however still allowed me to activate the feature on the second Web App's Site Collection (not sure why). This meant the second Web App didn't have a safe control entry in this Web.config file (and I was stupidly checking the first Web.config).
So, double-check you're looking at the correct web application/web.config.
Now I get a answer for similar problem as below:
When I try to added a new wep part to the page, then sharepoint show me a error message, tell me--Can not import my web part, this error message define in .webpart file.
So i tried to add some ohter web parts in the page , A strange quesiton appearance, some of them can be added , some of them can not be added.
After I traced the code of my web part and anaylsis them, I found the reason:
Old Code for web part ProjectInfo(my web part name) is:
namespace ProjectInfo
....
public class ProjectInfo:System.Web.UI.WebControls.WebParts.Web.part
{
.....
private SPWeb _spWeb;
private SPList _spList;
private string _listName = "ProjectDocs";
......
}
public ProjectInfo()
{
.....
_spWeb = SPContext.Current.Web;
//It show me a error here when i trace the code
_spList = _spWeb.Lists[_listName];
.....
}
Stop now, I thought that it maybe the web page init order problem. AS web page load web part control, constructrue function ProjectInfo() will be running at first. Actually, the web page havn't finish its init. by the time.
so i did a test. firstly, I put a good web in the page, it's ok . then, I try to put the web part in the page which can not be added just now. ~~ OK!! It's working ...because the page already init. finished.
Ok! I corrected my code:
namespace ProjectInfo
....
public class ProjectInfo:System.Web.UI.WebControls.WebParts.Web.part
{
.....
private SPWeb _spWeb;
private SPList _spList;
private string _listName = "ProjectDocs";
......
}
public ProjectInfo()
{
.....
//Remove code in constructure function.
//_spWeb = SPContext.Current.Web;
//It show me a error here when i trace the code
//_spList = _spWeb.Lists[_listName];
.....
}
protected override void CreateChildControls()
{
....
base.CreateChildControls();
_spWeb = SPContext.Current.Web;
_spList = _spWeb.Lists[_listName];
....
}
After I test, the error message did't happed again..
LoL ~~
Hope this explain will help you .
I have seen this anomaly several times without a good resolution.
Check that your Assembly, Namespace, Class name is correct EVERYWHERE. This has hung me up more than once.
Make sure you have a valid SafeControls entry.
Make sure your .webpart file is valid (let SharePoint create it for you if you can)
If you are absolutely positive that everything is correct, well then you are stuck in a place that I have been several times. The only thing that I can come up with is that VS is compiling the assembly wrong. The ONLY fix that I have found is to create a new VS project and set it up how you need, then copy THE TEXT of your old CS files into your new CS files...do not copy the files themselves...the goal is to have everything fresh.
This has worked for me. Good Luck.
Have you recycled your worker process or reset IIS?
Solved mine.
i was getting this error:
===========================================================================
Error importing WebPart. Cannot import ........ Web Part.
Failed to add webpart
Exception Microsoft.SharePoint.WebPartPages.WebPartPageUserException: Cannot import ... Web Part. at Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(Boolean clearConnections) at Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(SPWebPartManager manager, XmlReader reader, Boolean clearConnections, Uri webPartPageUri, SPWeb spWeb) at Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(SPWebPartManager manager, XmlReader reader, Boolean clearConnections, SPWeb spWeb) at Microsoft.SharePoint.WebPartPages.WebPartQuickAdd.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
===========================================================================
"Cannot import webpart..."
The problem was: Non-matching GUIDS
Check if the guid on webpart class , and in the .xml and in .webpart class are same.
I was copy-pasting code from other webparts sources. ( Mutliple Document Upload Wepart on Codeplex) and forgot to fix guids.
I have also experienced this error when the assemblies in the GAC that my web part referenced, was signed by a different strong name key file to what I was expecting.
I found this out when deciding to update these DLLs. When inserting it into the GAC I noticed that there were 2 entries for the same DLL but they had different Public Key Tokens
I got this error when I created a base class web part and then inherited a derived class from it. The base class was fine but the derived class failed when I tried to add it to a web page with the same error as the original post. In my case I had to add a public modifier to the class:
public class DerivedWebPart : BaseWebPart
Also I added a constructor in the derived class to call the base class one - although I think you shouldn't need this really:
public DerivedWebPart() : base()
{
}
I had a problem very similar to this, but Guids weren't the problem: my webpart didn't have the CLSCompliannt attribute set to false. Like so:
namespace MyNamespace
{
[CLSCompliant(false)]
[Guid("...")]
public class MyWidget : MyWebPartBaseClass
{
}
}
I found that mine did not import the first time, but if I clicked 'New' and added it, it would work.
From there I grabbed a copy of the XML and saved it to my project. The web part worked great after that.
It only took me DAYS to get to this point. A lot of wasted time.