Tuesday, January 7, 2014

BCS / BDC Full Tutorial

for some reasons all posts work upside down - make a step, see the error, fix.

so lets go from start to end. you have an sql table and you want it in your sharepoint as a list or for search.

OOTB you can do it with SQL, WCF, or .net assembly. with some code you can make it work with almost anything, but some1 has done it already for you: http://lightningtools.com/products/bcs-meta-man-2010-and-2013/. they also have an extension for VS2010 (only), very nice.

STEP 1: have a sharepoint farm, web, site collection and web.
well i am kinda counting on you here, create youself all that until you have a web with the ability to create lists.
STEP 2: have an external content source. with permissions.
in our case its gonna be an sql table. and so you need a user that will have permissions to walk around in your data, and it needs to be the same one that will get permission in the bcs, and he should have permissions to your site. you should give permissions according to the actions you want to do (add, delete, read ect.)

STEP 3: establish a bdc SERVICE. and connect your web app to it.
 Central Administration -> Manage Services on Server and make sure that the BDC service is on


go to your Central Administration -> Application Management (AM from now) -> Manage Service Application -> New -> Business Data Connectivity Service (from now BDC). you can give it any name you can dream about. give the bdc permissions for the same user as above.


connect your web app to it. go to your Central Administration -> Manage Web Applications -> [your web app] -> Service Connection -> check your fresh new BDC.



for some reason in order for the bcs to forward its permisions when it connects you must run this powershell:

$bcsServiceApp = Get-SPServiceApplication | where {$_ -match "Business Data Connectivity Service"}
$bcsServiceApp.RevertToSelfAllowed = $true;
$bcsServiceApp.Update();

dont forget to change the name to your BDC name.

STEP 4: create an external content type.
easy part (unless you use 3rd party like metaman), just open Designer -> External Content Types (side nav) -> External Content Type (ribbon) and give it a name.


get inside and the bottom left is "External Content Type Operations" with a like at the bottom "Clik here to discover...".
Add Connection -> SQL Server -> [all those credents] -> OK.
you should see the tree of your DB as you know it from SQL and choose a table, right click and "Create All Operations"


save your work and get back to the previous screen and in the ribbon click "Edit Connection Properties and change authentication mode to BDC's Identity.


STEP 5: create external list.
for that you must activate the web feature "team collaboration lists" (רשימות של שיתוף פעולה בצוות)
now go to your site content and click add app (or create list for 2010) and choose external list and choose your content type.

THATS IT! GL & HF!

for search i made another post: http://bresleveloper.blogspot.co.il/2014/07/see-database-sql-data-in-sharepoint.html

and last a general little tip - if any1 is using metaman or is creating a feature to deploy his external content type and then want to deploy it to another site you'll get an error, the solution is to also change the url property in the feature's xml:
<Properties>
    <Property Key='SiteUrl' Value='http://spf.u2ucourse.com'/>
</Properties>
more here: http://weblogs.asp.net/jan/sharepoint-2010-bdc-model-deployment-issue-the-default-web-application-could-not-be-determined

Monday, January 6, 2014

really adding WCF to sharepoint existing project

story is like this: we have a Sharepoint (10) solution, with already 12 (yep...) projects and we need a new service so... why another project? Sharepoint is a platform.

there are many sites explaining what and how to do it but i found them all being either too long, making it somehow too complex(msdn), or no accurate so i'll add mine.

my no.1 source: http://www.c-sharpcorner.com/UploadFile/anavijai/how-to-create-and-host-wcf-service-inside-sharepoint-2010/.

in the end its so simple: add a Sharepoint Mapped to ISAPI folder, inside create a new folder of your own service, and now you need inside there 4 files:
1. YourService.cs
2. IYourService.cs
3. YourService.svc
3. web.config (which is the main reason you want your own folder).

the inner content of the cs files copy from the url above, about the svc here is a simpler version:
<%@ServiceHost Language="C#" Debug="true" CodeBehind="fileOfClass.cs"    Service="yourNameSpace.yourClass, $SharePoint.Project.AssemblyFullName$"%>

and about the web.config i saw some mistakes so here is mine
<?xml version="1.0"?>
<configuration>
  <system.web>
    <!-- dont forget to remove this after dev is finish -->
    <customErrors mode="RemoteOnly"/>
  </system.web>
 
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="yourNameSpace.ServiceBehavior" name="yourNameSpace.yourClass">
        <endpoint address="" binding="basicHttpBinding" contract="yourNameSpace.yourInterface(like IService)">
          <identity>
            <!-- not sure yet if it will work in prod or not, after all its inner to the project, hope to update-->
            <dns value="localhost"/>
          </identity>
        </endpoint>

        <!-- this endpoint is to see service in browser, its removalbe -->
        <endpoint address="max" binding="mexHttpBinding" contract="IMetadataExchange"/>
       
        <host>
          <baseAddresses>
            <add baseAddress="http://yourServer:port(no need if its 80)/whatever you want/"/>
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="yourNameSpace.ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <!-- should be false in prod -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

  <!-- just in case -->
  <appSettings>
    <add key="someKey" value="someValue" />
  </appSettings>
 
</configuration>

now you probably read this because you want a service for your site, so here is how you open a web and log since your current web is your service, and also you shouldnt have permissions (btw when you run it start with a method bool that just return true to be sure that it works):
public string ExploreSite()
{
    try
    {
       string result = string.Empty;
       SPSecurity.RunWithElevatedPrivileges(() =>
       {
           string siteUrl = ConfigurationManager.AppSettings["siteUrl"];
           using (SPSite site = new SPSite(siteUrl))
           {
               using (SPWeb web = site.OpenWeb())
               {
                   result = web.Name;
               }
           }
           });
           return result;
    }
    catch (Exception ex)
    {
          string m = ex.Message;
          SPSecurity.RunWithElevatedPrivileges(() =>
          {
              if (EventLog.SourceExists("yourSource") == false)
              EventLog.CreateEventSource(new EventSourceCreationData("yourSource", "create"));
              while (ex.InnerException != null)
              {
                  ex = ex.InnerException;
                  m += Environment.NewLine + ex.Message;
              }
              EventLog.WriteEntry("yourSource", ex.Message, EventLogEntryType.Error);
          });
          return m;
    }
}

note:
1. to refresh the code for a client you need to rebuild and recycle the pool. for debugging the same but it seems to fail sometimes if not called before by a client (no the browser).
2. in this case you dont need to worry about problems caused by a service being in .Net 4 vs the SP10 which is 3.5, and also you dont need to work hard for your web.config as usual for WCF in 3.5 since its all inside your already existing site.

fighting IE

well, lets start that IE is not a browser, as in just a web browser with a web kit, its more, like the SP optimizations and other programs you can build into it. that could be great if not that MS wants to dedicate it to web browsing too.

so any1 that tried to build a nice page will understand this:http://funny-pics-fun.com/wp-content/uploads/Demotivational-Posters-Internet-Explorer-6.jpg
its about 6 but relevant forever

anyway this proj i really had to fight it, and its not fun :(

simplest solution to most situations where it just look great everywhere and IE just MUST move it aside a few pic is to make another IE only css file, and load it after the main
<!--[IF IE]><link  rel="stylesheet" type="text/css" href="/Style%20Library/Nifgashim/Styles/IE.css"><![endif]-->

you can put there other solutions i will mention as well.

Problem: anchor hovering (a:hover), and hovering in general doesnt work!
i found that this problem is caused when you use floaters in your page, meaning that your element or one of its parents id a floater (has css float:somehing).
that horrible since today we have responsive designs and its all float based ?!
anyway i found that changing the elements prop position to relative solves the problem.

Problem: you want an empty span or element with only background image.
so u use the wonderful &nbsp; - but in IE it doesnt work. the only solution i found is to put a nested element with no opacity, like this:
<span class="hereWeWantBG">
<![IF !IE]>&nbsp;<![endif]>
<!--[IF IE]><span class="IEInvisability">content</span><![endif]-->
</span>

.IEInvisability{-moz-opacity: 0.00;opacity: 0.00;filter: alpha(opacity=00);display:inline-block;}
if memory serves you only need the filter prop, but this is copied from another element where i wanted it to be with no opacity at all so test it. also yes you need it to be inline-block.

Problem: yes IE no IE in html - answer as above.