-----------------------------------

Acquista i software ArcGIS tramite Studio A&T srl, rivenditore autorizzato dei prodotti Esri.

I migliori software GIS, il miglior supporto tecnico!

I migliori software GIS, il miglior supporto tecnico!
Azienda operante nel settore GIS dal 2001, specializzata nell’utilizzo della tecnologia ArcGIS e aderente ai programmi Esri Italia Business Network ed Esri Partner Network

-----------------------------------



venerdì 24 aprile 2009

Query Builder & Print SOE x MapViewer

Nel result task del Map Viewer se vuoi visualizzare le descrizioni del dominio aggiungi questa funzione in ESRI.ArcGIS.NITK -> Framework -> Results -> ResultProductiongTask.cs


/// <summary>
        /// Set the Results after applying renderers and IS_SELECTED column of the graphics layer to true.
        /// </summary>
        /// <param name="dtResults">Contains the data of the graphics layer.</param>
        /// <param name="sResourceName">Name of the resource to apply renderers.</param>
        /// <param name="sLayerId">Name of the layer Id to apply renderers.</param>        
        /// <param name="bSetAsSelected">Whether to set IsSelected column of graphics layer to true.</param>
        public void SetResults(ref DataTable dtResults, string sResourceName, string sLayerId, bool bSetAsSelected)
        {
            try
            {
                if (dtResults == null  dtResults.Rows.Count == 0)
                {
                    NoSelectionsTaskResult taskResult = new NoSelectionsTaskResult(this.Title);
                    Results = taskResult;
                }
                else
                {
 
                    dtResults = LoadDomainValues(dtResults); //<- add this function 
 
                ......


public DataTable LoadDomainValues(DataTable dt)
        {
            try
            {
                IDictionary<String, IDictionary<Int32, String>> dc = null;
                MapResourceLocal mr = (MapResourceLocal)Map.PrimaryMapResourceInstance;
                ESRI.ArcGIS.Carto.IMapServerObjects mso = (ESRI.ArcGIS.Carto.IMapServerObjects)mr.MapServer;
 
                ESRI.ArcGIS.Carto.ILayer layer = null;
 
 
                ESRI.ArcGIS.Carto.IMap map = mso.get_Map(mr.MapServer.DefaultMapName);
 
 
                ESRI.ArcGIS.Carto.IEnumLayer enumLayer = map.get_Layers(null, true);
                ESRI.ArcGIS.Carto.ILayer loopLayer = null;
                while ((loopLayer = enumLayer.Next()) != null)
                {
                    if (loopLayer.Name == dt.TableName)
                    {
                        layer = loopLayer;
                        break;
                    }
                }
 
                ESRI.ArcGIS.Carto.IFeatureLayer fl = (ESRI.ArcGIS.Carto.IFeatureLayer)layer;
                ESRI.ArcGIS.Geodatabase.IFeatureClass fclass = fl.FeatureClass;
                ESRI.ArcGIS.Geodatabase.IFields flds = fclass.Fields;
                ESRI.ArcGIS.Geodatabase.IDomain d = null;
                ESRI.ArcGIS.Geodatabase.ICodedValueDomain cvd = null;
 
                dc = new Dictionary<String, IDictionary<Int32, String>>();
 
 
                IDictionary<Int32, String> dm = null;
                ESRI.ArcGIS.Geodatabase.IField f = null;
                for (Int32 fi = 0; fi < flds.FieldCount; fi++)
                {
                    f = flds.get_Field(fi);
                    d = f.Domain;
                    if (d == null)
                        dm = null;
                    else
                    {
                        cvd = (ESRI.ArcGIS.Geodatabase.ICodedValueDomain)d;
                        dm = new Dictionary<Int32, String>();
                        for (Int32 i = 0; i < cvd.CodeCount; i++)
                            dm.Add(Convert.ToInt32(cvd.get_Value(i)), cvd.get_Name(i));
                    }
                    dc.Add(f.Name, dm);
                }
 
                IDictionary<Int32, String> listDomain = null;
                DataTable dtnew = dt.Clone();
                foreach (DataColumn c in dtnew.Columns)
                {
                    if (dc.ContainsKey(c.ColumnName))
                    {
                        listDomain = dc[c.ColumnName];
                        if (listDomain != null)
                            c.DataType = System.Type.GetType("System.String");
                    }
                }
 
 
                DataRow newRow;
                foreach (DataRow r in dt.Rows)
                {
 
                    newRow = dtnew.NewRow();
                    foreach (DataColumn c in dt.Columns)
                    {
                        if (dc.ContainsKey(c.ColumnName))
                        {
                            listDomain = dc[c.ColumnName];
                            if (listDomain == null)
                                newRow[c.ColumnName] = r[c.ColumnName];
                            else
                            {
                                if (!(r[c.ColumnName] is DBNull))
                                    newRow[c.ColumnName] = listDomain[Convert.ToInt32(r[c.ColumnName])];
                            }
                        }
                        else
                            newRow[c.ColumnName] = r[c.ColumnName];
                    }
                    dtnew.Rows.Add(newRow);
                }
                return dtnew;
            }
            catch (Exception ex)
            {
                _log.Error("Error in LoadDomainValues", ex);
                return dt;
 
            }
 
        }





Scarica qui il task Query Builder x MapViewer

Scarica qui il task Layout SOE x MapViewer (versione semplificata: solo PDF)

domenica 19 aprile 2009

Unit Tests

Perché utilizzare gli Unit Tests?
Mentre guidi per andare al lavoro una mattina, hai una improvvisa intuizione riguardo all’applicazione su cui stai lavorando. Ti rendi conto che puoi implementare una modifica che ottimizzerà drasticamente l’applicazione. Potrebbe trattarsi di un refactoring che rende il nostro codice più leggibile, aggiunge una nuova funzionalità o corregge un bug.
La domanda che ti viene spontanea è: “Quanto è sicuro apportare questo miglioramento?” E se il cambiamento ha effetti collaterali indesiderati? La modifica sarà anche semplice e richiede pochi minuti, ma se ci volessero ore di test manuali su tutti gli scenari applicativi? E se te ne dimentichi uno e l’applicazione va in produzione? L'intuizione che hai avuto vale il rischio?


Gli unit test automatizzati possono fornire una maggiore sicurezza che ti consente di migliorare costantemente le tue applicazioni e di non temere il codice su cui stai lavorando. Avere test automatizzati che verificano rapidamente la funzionalità ti permette di controllare con sicurezza e di apportare miglioramenti che altrimenti non avresti osato fare. Ti aiutano inoltre a creare soluzioni a lungo termine: il che costituisce un notevole ritorno sull’investimento.


Il framework NET rende facile e naturale adottare unit test e consente Test Driven Development workflow che garantisce a sua volta lo sviluppo basato su test first.








Vediamo un semplice esempio con Visual Studio 2008 Professional:


Creiamo una semplice tabella in SQL Express:











Ora aggiungiamo al progetto un LINQ to SQL Classes:



Ora con un semplice drag portiamo la tabella sul designer dell'item inserito. Con questa operazione verrà creata una classe usando lo schema della tabella (le proprietà della classe mappano le colonne della tabella).


In automatico, poichè la tabella si chiama Persone, verrà creata una classe di nome persone (è possibile comunque cambiare i nomi sia delle tabelle che delle proprietà).

Ora aggiungiamo un nostro metodo alla classe. Per questo ci viene incontro la parola chiave
partial che permette di aggiungere metodi, proprietà ed eventi ad una classe già esistente senza toccarla.


partial class Persone
    { 
       public bool IsValid()
       {
           return (this.Cognome != string.Empty) && (this.Nome != string.Empty);
       }
    }


Ora creiamo una classe di helper per gestire le persone:


public class PersoneRepository
    {
 
 
        private dcPersoneDataContext db = new dcPersoneDataContext();
 
 
 
 
 
        public IQueryable<Persone> Persone() {
                return db.Persones;
        }
 
        public IQueryable<Persone> ListPersoneDaCitta(string Citta)
        {
          return (from persona in db.Persones
                 where persona.Città == Citta
                 orderby persona.Cognome
                 select persona).AsQueryable();
        }
 
        public Persone GetPersona(Guid id) {
            return db.Persones.SingleOrDefault(d => d.Id == id);
        }
 
        public void Add(Persone persona)
        {
            db.Persones.InsertOnSubmit(persona);
        }
        public void Delete(Persone persona)
        {
            db.Persones.DeleteOnSubmit(persona);
        }
 
        public void Save() {
          db.SubmitChanges();
        }
 
 
    }


Ora alla soluzione aggiungiamo un progetto di test:


E aggiungiamo i seguenti metodi:


[TestClass]
    public class PersoneTest
    {
 
        [TestMethod]
        public void PersoneNonCorrettoQuandoUnaProprietàNonèCorretta()
        {
 
            Persone persona = new Persone()
            {
                Nome="Nico", 
                Cognome ="", 
                Telefono="10212092340",
                CAP="20052", 
                Indirizzo="Via Lario 10", 
                Città="Monza"
            };
 
            bool isValid = persona.IsValid();
 
            Assert.IsFalse(isValid);
        }
 
        [TestMethod]
        public void PersoneCorrettoQuandoTutteProprietàSonoCorrette()
        {
 
            Persone persona = new Persone()
            {
                Nome = "Nico",
                Cognome = "Ciavarella",
                Telefono = "10212092340",
                CAP = "20052",
                Indirizzo = "Via Lario 10",
                Città = "Monza"
            };
 
            bool isValid = persona.IsValid();
 
            Assert.IsTrue(isValid);
        } }



In questo caso testiamo quando una proprietà non è corretta (non è stato assegnato il cognome) e quando tutte le proprietà sono formalmente corrette. Nel metodo IsValid() controlliamo che il nome ed il cognome non siano vuoti.

Il nome del singolo test deve essere molto esplicativo visto che in un progetto potresti avere migliaia di piccoli test. Usa un naming pattern tipo "Noun_Should_Verb".

Quando scriviamo dei test dobbiamo evitare di avere singoli test che fanno troppe cose.
E' buona norma invece che ogni singolo test verifichi un solo concetto (anche perchè facilita la causa del fallimento di un singolo test). Una buona pratica per realizzare questo è avere un singolo assert per ogni test. Se hai più di un assert in un metodo di test, assicurati che questi rappresentino lo stesso concetto. Se hai dei dubbi, fai un altro test.

Ora da Visual Studio lanciamo tutti i test della soluzione:






Ora aggiungiamo al nostro progetto una classe che utilizza la PersoneRepository


public class PersoneController
    {
        PersoneRepository m_personeRepository;
 
        public PersoneRepository PersoneRepository
        {
            get { return m_personeRepository; }
            set { m_personeRepository = value; }
        }
        public PersoneController()
        {
            m_personeRepository = new PersoneRepository();
        }
        public PersoneController(PersoneRepository repository)
        {
            m_personeRepository = repository;
        }
    }


e nel progetto di test aggiungiamo un nuovo metodo che verifica se il ListPersoneDaCitta è corretto:


PersoneRepository getPersoneRepository()
        {
            Persone persone = new Persone() { Nome = "Nico", Cognome = "Ciavarella", Telefono = "10212092340", CAP = "20052", Indirizzo = "Via Lario 10", Città = "Monza" };
            PersoneRepository p = new PersoneRepository();
            p.Add(persone);
            return p;
        }
 
 
        [TestMethod]
        public void ListaPersoneInCittaCorretto()
        {
            PersoneController p = new PersoneController(getPersoneRepository());
            var j = p.PersoneRepository.ListPersoneDaCitta("Monza");
 
            Assert.IsTrue(j.Count() == 1);
        }


Se lanciamo tutti i test del progetto avremo:


Se guardiamo al messaggio di errore, vediamo che il test fallisce perchè la nostra classe PersoneRepository nel progetto di test non è abilitata a connettersi al database. La nostra applicazione si sta connettendo ad un SQL Server Express locale. Potremmo modificare nel nostro progetto di test aggiungendo il database SQL Express e aggiungendo nell'App.Config la connection string. In questo modo il nostro test verrebbe eseguito correttamente.
Utilizzare reali connessioni al database negli unit test comporta una serie di sfide:
- l'esecuzione di unit test rallenta significativamente. Più sono lenti, meno frequentemente avvieremo la loro esecuzione. Idealmente noi vorremmo che fossero velocissimi e che fossero come compilare un progetto.
- noi vorremmo che ogni unit test fosse isolato ed indipendente dagli altri (nessun effetto di dipendenza). Quando lavoriamo con database reali, dovremmo sempre considerare il loro stato e reimpostarlo ad ogni avvio di test. In questo caso ci viene incontro il pattern chiamato "
dependency injection", che aiuta a lavorare intorno al problema e ad evitare di lavorare con database reali nei test.

Dependency injection

In pratica dobbiamo disaccoppiare la nostra classe PersoneRepository che accede al database:

Estraiamo dalla classe l'interfaccia relativa:




Ora la nostra classe implementa l'interfaccia IPersoneRepository:


public class PersoneRepository : IPersoneRepository
    {
 
 
        private dcPersoneDataContext db = new dcPersoneDataContext();
 
 
 
 
 
        public IQueryable<Persone> Persone() {
                return db.Persones;
        }
 
        public IQueryable<Persone> ListPersoneDaCitta(string Citta)
        {
          return (from persona in db.Persones
                 where persona.Città == Citta
                 orderby persona.Cognome
                 select persona).AsQueryable();
        }
 
        public Persone GetPersona(Guid id) {
            return db.Persones.SingleOrDefault(d => d.Id == id);
        }
 
        public void Add(Persone persona)
        {
            db.Persones.InsertOnSubmit(persona);
        }
        public void Delete(Persone persona)
        {
            db.Persones.DeleteOnSubmit(persona);
        }
 
        public void Save() {
          db.SubmitChanges();
        }
 
 
    }


Questa è la definizione dell'interfaccia:


public interface IPersoneRepository
    {
        void Add(Persone persona);
        void Delete(Persone persona);
        Persone GetPersona(Guid id);
        System.Linq.IQueryable<Persone> ListPersoneDaCitta(string Citta);
        System.Linq.IQueryable<Persone> Persone();
        void Save();
    }


Modifichiamo di conseguenza anche la nostra classe che utilizza la PersoneRepository:


public class PersoneController
    {
        IPersoneRepository m_personeRepository;
 
        public IPersoneRepository PersoneRepository
        {
            get { return m_personeRepository; }
            set { m_personeRepository = value; }
        }
        public PersoneController()
        {
            m_personeRepository = new PersoneRepository();
        }
        public PersoneController(IPersoneRepository repository)
        {
            m_personeRepository = repository;
        }
    }


Ora nel progetto di test creiamo una classe 'finta' che simula il database:


public class FakePersoneRepository : IPersoneRepository
    {
 
        private List<Persone> personeList;
 
        public FakePersoneRepository(List<Persone> persone)
        {
            personeList = persone;
        }
 
        #region IPersoneRepository Members
 
        public void Add(Persone persona)
        {
            personeList.Add(persona);
        }
 
        public void Delete(Persone persona)
        {
            personeList.Remove(persona);
        }
 
        public Persone GetPersona(Guid id)
        {
            return personeList.SingleOrDefault(d => d.Id == id);
        }
 
        public IQueryable<Persone> ListPersoneDaCitta(string Citta)
        {
            return (from p in personeList
                    where p.Città == Citta
                    orderby p.Cognome
                    select p).AsQueryable();
        }
 
        public IQueryable<Persone> Persone()
        {
            return personeList.AsQueryable();
        }
 
        public void Save()
        {
            foreach (Persone p in personeList)
            {
                if (!p.IsValid())
                    throw new ApplicationException("Persona non valida!");
            }
        }
 
        #endregion
    }



Ed infine modifichiamo il nostro test precedente che falliva:


IPersoneRepository getPersoneRepository()
        {
            Persone persone = new Persone() { Nome = "Nico", Cognome = "Ciavarella", Telefono = "10212092340", CAP = "20052", Indirizzo = "Via Lario 10", Città = "Monza" };
            List<Persone> ListPersone = new List<Persone>();
            ListPersone.Add(persone);
            return new FakePersoneRepository(ListPersone);
        }
 
        [TestMethod]
        public void ListaPersoneInCittaCorretto()
        {
            PersoneController p = new PersoneController(getPersoneRepository());
            var j = p.PersoneRepository.ListPersoneDaCitta("Monza");
 
            Assert.IsTrue(j.Count() == 1);
        }


Comunque la Dependency Injection è solo una delle possibili sfide quando si creano unit test, dal momento che nelle reali applicazioni ci sono svariate dipendenze che occorre risolvere con oggetti 'finti'.

domenica 5 aprile 2009

Simple Photo gallery per MapViewer

This is a simple task to visualize a photo list associated to a feature: the task was developed integrating it in the map viewer ( http://resources.esri.com/arcgisserver/adf/dotnet/index.cfm?fa=codeGalleryDetails&scriptID=15963 ) framework. In the code, you will have to point out the id layer and the field name on which the feature must be searched (variable LayerId and fieldName). Besides, in the static function LoadImages you will have to write your business logic in order to get back the photo list.
For instance, in this function I get back the photo list from a table (many) joined with the feature class passing to the function the value in fieldName in feature class (one). In this particular case the join is between ObjectId in feature class and the relevant value in a many table field, while the value searched in input in the user's floating panel is another one, in this case the fieldName string type field parameter key passed to the function. The last sentence highlights that, if the field is of numeric type, the apostrophes in the query must be removed.
The function returning the photo list could become more than one because it can be modified in runtime (through the property methodImages) as it is called via reflection.




 
 
namespace Studioat.ARCGIS.ADF.Tasks
{
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Data.OleDb;
using System.Reflection;
using System.Text;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using ESRI.ArcGIS.ADF.Web;
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web.UI.WebControls;
using ESRI.Solutions.NITK.Framework.Results;
using ESRI.Solutions.NITK.Framework.TaskResults;
//Author: Domenico Ciavarella
//www.studioat.it
[AjaxControlToolkit.ClientScriptResource("Studioat.ARCGIS.ADF.Tasks.PhotoGalleryTask", "Studioat.ARCGIS.ADF.Tasks.javascript.PhotoGalleryTask.js")]
[System.Web.UI.ToolboxData(@"<{0}:PhotoGalleryTask runat=""server"" BackColor=""White""
        BorderColor=""LightSteelBlue"" BorderStyle=""Outset"" BorderWidth=""1px"" Font-Names=""Verdana""
        Font-Size=""8pt"" ForeColor=""Black"" TitleBarColor=""WhiteSmoke"" TitleBarHeight=""20px""
        TitleBarSeparatorLine=""True"" Transparency=""35"" Width=""130px"">
        </{0}:PhotoGalleryTask>")]
public class PhotoGalleryTask : ResultProducingTask
{
static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
static readonly string taskFullName = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName;
static readonly string taskNamespace = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;
ITaskResultsContainer m_TaskResults;
//Change here your data
//*********************************************************
string LayerId = "1";
string fieldName = "YourNameFieldSearchUserFeature";
//*********************************************************
[Browsable(true)]
[Category("PhotoGalleryTask")]
[DefaultValue("LoadImages")]
[PersistenceMode(PersistenceMode.Attribute)]
[DisplayName("Method for list images")]
public string MethodImages
{
get
{
object o = StateManager.GetProperty("methodImages");
return (o == null) ? "LoadImages" : o as string;
}
set
{
StateManager.SetProperty("methodImages", value);
}
}
        #region CreateChildControls, Render
HtmlGenericControl container = null;
HtmlGenericControl containerDivPG = null;
Image progressImage = null;
Image htmlPrevButton = null;
Image htmlNextButton = null;
HtmlGenericControl containerDiv = null;
Image photoImage = null;
public HtmlInputText txtValue = null;
public HtmlInputButton btnFind = null;
protected override void CreateChildControls()
{
Controls.Clear();
base.CreateChildControls();
container = new HtmlGenericControl("div");
container.ID = "photoGallery";
Controls.Add(container);
containerDivPG = new HtmlGenericControl("div");
container.Controls.Add(containerDivPG);
htmlPrevButton = new Image();
htmlPrevButton.ID = "prevButton";
htmlPrevButton.ImageUrl = GetSource("backDisabled.png");
containerDivPG.Controls.Add(htmlPrevButton);
htmlNextButton = new Image();
htmlNextButton.ID = "nextButton";
htmlNextButton.ImageUrl = GetSource("forwardDisabled.png");
containerDivPG.Controls.Add(htmlNextButton);
progressImage = new Image();
progressImage.ID = "progress";
progressImage.ImageUrl = GetSource("activity_indicator.gif");
containerDivPG.Controls.Add(progressImage);
containerDiv = new HtmlGenericControl("div");
container.Controls.Add(containerDiv);
photoImage = new Image();
photoImage.ID = "image";
photoImage.ImageUrl = GetSource("gray_x_button.gif");
containerDiv.Controls.Add(photoImage);
txtValue = new HtmlInputText();
txtValue.ID = "txtValue";
Controls.Add(txtValue);
btnFind = new HtmlInputButton();
btnFind.ID = "btnFind";
btnFind.Value = "Find";
Controls.Add(btnFind);
StringBuilder KeyValues = new StringBuilder();
KeyValues.Append(string.Format("'{0}=' + $get('{1}').value", "txtFindValue", txtValue.ClientID));
string onClick = string.Format("executeTask({0},\"{1}\");", KeyValues.ToString(), CallbackFunctionString);
btnFind.Attributes.Add("onclick", onClick);
}
        #endregion
private string GetSource(string image)
{
return Page.ClientScript.GetWebResourceUrl(typeof(PhotoGalleryTask), string.Format("{0}.images.{1}", taskNamespace, image));
}
protected override void OnPreRender(System.EventArgs e)
{
base.OnPreRender(e);
if (!base.IsAsync)
{
RegisterScriptControl();
}
}
protected string ControlClientID
{
get
{
EnsureChildControls();
return container.ClientID;
}
}
void RegisterScriptControl()
{
StringBuilder script = new StringBuilder();
script.Append("Sys.Application.add_init(function() {");
script.AppendFormat("$create({0},",taskFullName);
script.Append("{");
script.AppendFormat("'imageElement': $get('{0}'),", photoImage.ClientID);
script.AppendFormat("'prevElement': $get('{0}'),", htmlPrevButton.ClientID);
script.AppendFormat("'nextElement': $get('{0}'),", htmlNextButton.ClientID);
script.AppendFormat("'progressElement': $get('{0}'),", progressImage.ClientID);
script.AppendFormat("'forwardDisabledUrl': '{0}',", GetSource("forwardDisabled.png"));
script.AppendFormat("'backwardDisabledUrl': '{0}',", GetSource("backDisabled.png"));
script.AppendFormat("'forwardUrl': '{0}',", GetSource("forward.png"));
script.AppendFormat("'backwardUrl': '{0}',", GetSource("back.png"));
script.AppendFormat("'noPhotoUrl': '{0}',", GetSource("gray_x_button.gif"));
script.Append("'images': []");
script.AppendFormat("}}, {{}}, {{}}, $get('{0}'));", ControlClientID);
script.AppendLine("});");
System.Web.UI.ScriptManager.RegisterStartupScript(this, this.GetType(), this.ClientID + "_startup", script.ToString(), true);
}
/// <summary>
/// sample method used for list of images
/// </summary>
/// <param name="key">your key</param>
/// <returns>string: 'http://www.myphoto.com/01.jpg','http://www.myphoto.com/02.jpg' or string.Empty</returns>
static string LoadImages(string key)
{
//********************************************************************************
//change with your code. This is an example.
//********************************************************************************
string connectionString = ConfigurationManager.AppSettings["ConnectionDB"];
string pathFoto = ConfigurationManager.AppSettings["PhysicalPathFoto"];
string queryString = "SELECT Photo from featureclassOne,tableMany "
+ "WHERE (featureclassOne.objectid = tableMany.foreignKey) and (YourFieldName = ?)";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(queryString, connection);
command.Parameters.AddWithValue("@key", key);
try
{
string result=null;
connection.Open();
using (OleDbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
result += string.Format("'{0}{1}{2}",pathFoto, reader[0].ToString().Replace("\\","/"),"',");
}
}
result = result.Substring(0, result.Length - 1);
return result;
}
catch
{
return string.Empty;
}
}  
}
public override void ExecuteTask()
{
Results = null;
if (Input == null) return;
NameValueCollection keyValColl = Input as NameValueCollection;
string stxtFindValue = keyValColl["txtFindValue"] as string;
string sWhere = string.Format("{0} = {2}{1}{2}", fieldName, stxtFindValue,"'");
ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisresource = Map.PrimaryMapResourceInstance;
IQueryFunctionality queryFunctionality = (IQueryFunctionality)gisresource.CreateFunctionality(typeof(IQueryFunctionality), null);
SpatialFilter spatialfilter = new SpatialFilter();
spatialfilter.ReturnADFGeometries = true;
spatialfilter.MaxRecords = 1;
spatialfilter.WhereClause = sWhere;
System.Data.DataTable datatable = queryFunctionality.Query(null, LayerId, spatialfilter);
if ((datatable == null)  (datatable.Rows.Count == 0))
{
NoSelectionsTaskResult setResultsTaskResult = new NoSelectionsTaskResult((datatable == null) ? "Error!" : "No found value!");
Results = setResultsTaskResult;
return;
}
try
{
SetResults(ref datatable, null, LayerId, true);
TaskResults.DisplayResults(null, null, null, this.Results);
TaskResults.Show();
MethodInfo dynMethod = GetType().GetMethod(MethodImages, BindingFlags.NonPublic  BindingFlags.Static);
object o = dynMethod.Invoke(this, new object[] { stxtFindValue });
CallbackResults.Add(CallbackResult.CreateJavaScript(string.Format("$find('{0}').set_images([{1}]);", ControlClientID, o)));
}
catch (Exception ex)
{
UnableToSetResultsTaskResult setResultsTaskResult = new UnableToSetResultsTaskResult(this.Title, ex.Message);
Results = setResultsTaskResult;
}
}
private ITaskResultsContainer TaskResults
{
get
{
if ((m_TaskResults == null) && (TaskResultsContainers[0] != null))
m_TaskResults = ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl(TaskResultsContainers[0].Name, Page) as ITaskResultsContainer;
return m_TaskResults;
}
}
public override string GetCallbackResult()
{
NameValueCollection keyValColl = CallbackUtility.ParseStringIntoNameValueCollection(CallbackEventArgument);
Input = keyValColl;
return base.GetCallbackResult();
}
public override List<GISResourceItemDependency> GetGISResourceItemDependencies()
{
throw new System.NotImplementedException();
}
}
}

Here you can download the source code http://resources.esri.com/arcgisserver/adf/dotnet/index.cfm?fa=codeGalleryDetails&scriptID=16219

Preview:








For Adalmj:
I used the same logic as this sample
and from the task I pass information to maptips

"if (result.StreetView != '')" +
                       "      {{" +
                              "mapTips.add_expanded(ExpandMapTips);" +
                              "mapTips.set_width(405);" +
                              "mapTips.set_maxheight(350);" +
                              "mapTips.set_contentTemplate('<span><b><a href=\'{{@StreetView}}\' target=\'_blank\'>Street View</a><br><br><a href=\'{{@GoogleMaps}}\' target=\'_blank\'>Google Maps</a></b></span><div onclick=\'var coords = new GLatLng({{@Lat}},{{@Lon}});panoramaOptions = {{ latlng:coords }};var myPano = new GStreetviewPanorama($get(""{{@Id}}""), panoramaOptions);\' name=\'{{@Id}}\' id=\'{{@Id}}\' style=\'width: 400px; height: 300px\'></div>');" +
                              "}}";