After using Android layout this.SetContentView(Resource.Layout.Main), and LoadApplication(new App()), I could not see Xamarin.Forms MainPage.xaml. I tried to remove the Linear Layout, but it just removing items inside them, not the form itself. It seems like SetContentView blocking the Xamarin.Forms. So,
Here is MainActivity.cs:
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Text.Method;
using Android.Widget;
using Auth0.OidcClient;
using IdentityModel.OidcClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace IndoFellowship.Droid {
// Define App icon and name
[Activity(
Label = "Indo App",
MainLauncher = true,
Icon = "#drawable/icon",
LaunchMode = LaunchMode.SingleTask)
]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity {
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
// Showing layout that I set
SetContentView(Resource.Layout.Main);
// Do login
// Some codes
// Done processing on Android, I need to load Xamarin.Forms
LinearLayout mainLayout = (LinearLayout)FindViewById(Resource.Id.mainLayoutID);
mainLayout.RemoveAllViews();
// Load App
LoadApplication(new App());
}
}
}
Main.axml on Resources/values/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayoutID"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
// Some layout here..
</LinearLayout>
and my App.xaml.cs (Xamarin)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace IndoFellowship {
public partial class App : Application {
public static string AppName { get; set; }
public App() {
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
protected override void OnStart() {
// Handle when your app starts
}
protected override void OnSleep() {
// Handle when your app sleeps
}
protected override void OnResume() {
// Handle when your app resumes
}
}
}
MainPage.xaml.cs (Xamarin)
using Auth0.OidcClient;
using IdentityModel.OidcClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Auth;
using Xamarin.Forms;
namespace IndoFellowship
{
public partial class MainPage : ContentPage {
public MainPage()
{
InitializeComponent();
var browser = new WebView();
browser.Source = "http://xamarin.com";
Content = browser;
}
}
}
Over here I should seeing xamarin.com webView, but my Android just went blank. It seems like Xamarin.Forms not showing at all and I am still on Xamarin.Android. If I took SetContentView, I can see the forms rendered perfectly, but I could not process what I need to do on Android.
What I need to do to properly load Xamarin Forms from MainActivity?
Why layout not removed?
Thank you.
I found my solution by using StartActivity instead of LoadApplication.
By creating a second activity:
XamarinForms.cs this activity load the app()
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace IndoFellowship.Droid {
[Activity(Label = "XamarinForm")]
public class XamarinForm : Xamarin.Forms.Platform.Android.FormsApplicationActivity {
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
}
}
MainActivity.cs instead of LoadApplication here, I am calling the second activity instead
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Text.Method;
using Android.Widget;
using Auth0.OidcClient;
using IdentityModel.OidcClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace IndoFellowship.Droid {
// Define App icon and name
[Activity(
Label = "Indo App",
MainLauncher = true,
Icon = "#drawable/icon",
LaunchMode = LaunchMode.SingleTask)
]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity {
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
// Showing layout that I set
SetContentView(Resource.Layout.Main);
// Do login
// Some codes
// Done processing on Android, I need to load Xamarin.Forms
LinearLayout mainLayout = (LinearLayout)FindViewById(Resource.Id.mainLayoutID);
mainLayout.RemoveAllViews();
// Load App
StartActivity(typeof(XamarinForms));
}
}
}
May be this is not a best design since now I have two activities. Please let me know if you know better way to accomplish this. Thank you.
Related
So we have a working ServiceStack service hosted inside a Windows Service using .Net 4.6.2, which uses a bunch of Fluent Validation validators.
We would like to port this to .Net Core. So I started to create cut down project just with a few of the features of our main app to see what the port to .Net Core would be like.
Most things are fine, such as
IOC
Routing
Hosting
Endpoint is working
The thing that does not seem to be correct is validation. To illustrate this I will walk through some existing .Net 4.6.2 code and then the .Net Core code. Where I have included the results for both
.NET 4.6.2 example
This is all good when using the full .Net 4.6.2 framework and the various ServiceStack Nuget packages.
For example I have this basic Dto (please ignore the strange name, long story not my choice)
using ServiceStack;
namespace .RiskStore.ApiModel.Analysis
{
[Route("/analysis/run", "POST")]
public class AnalysisRunRequest : BaseRequest, IReturn<AnalysisRunResponse>
{
public AnalysisPart Analysis { get; set; }
}
}
Where we have this base class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace .RiskStore.ApiModel
{
public abstract class BaseRequest
{
public string CreatedBy { get; set;}
}
}
And we have this validator (we have way more than this working in .Net 4.6.2 app, this is just to show differences between full .Net and .Net Core which we will see in a minute)
using .RiskStore.ApiModel.Analysis;
using ServiceStack.FluentValidation;
namespace .RiskStore.ApiServer.Validators.Analysis
{
public class AnalysisRunRequestValidator : AbstractValidator<AnalysisRunRequest>
{
public AnalysisRunRequestValidator(AnalysisPartValidator analysisPartValidator)
{
RuleFor(analysis => analysis.CreatedBy)
.Must(HaveGoodCreatedBy)
.WithMessage("CreatedBy MUST be 'sbarber'")
.WithErrorCode(ErrorCodes.ValidationErrorCode);
}
private bool HaveGoodCreatedBy(AnalysisRunRequest analysisRunRequest, string createdBy)
{
return createdBy == "sbarber";
}
}
}
And here is my host file for this service
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Funq;
using .RiskStore.ApiModel.Analysis;
using .RiskStore.ApiModel.Analysis.Results;
using .RiskStore.ApiServer.Api.Analysis;
using .RiskStore.ApiServer.Exceptions;
using .RiskStore.ApiServer.IOC;
using .RiskStore.ApiServer.Services;
using .RiskStore.ApiServer.Services.Results;
using .RiskStore.ApiServer.Validators.Analysis;
using .RiskStore.ApiServer.Validators.Analysis.Results;
using .RiskStore.DataAccess.AnalysisRun.Repositories.Results;
using .RiskStore.DataAccess.AnalysisRun.Repositories.Search;
using .RiskStore.DataAccess.AnalysisRun.Repositories.Validation;
using .RiskStore.DataAccess.Configuration;
using .RiskStore.DataAccess.Connectivity;
using .RiskStore.DataAccess.Ingestion.Repositories.EventSet;
using .RiskStore.DataAccess.JobLog.Repositories;
using .RiskStore.DataAccess.StaticData.Repositories;
using .RiskStore.DataAccess.UnitOfWork;
using .RiskStore.Toolkit.Configuration;
using .RiskStore.Toolkit.Jobs.Repositories;
using .RiskStore.Toolkit.Storage;
using .RiskStore.Toolkit.Utils;
using .Toolkit;
using .Toolkit.Configuration;
using .Toolkit.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ServiceStack;
using ServiceStack.Text;
using ServiceStack.Validation;
namespace .RiskStore.ApiServer.Api
{
public class ApiServerHttpHost : AppHostHttpListenerBase
{
private readonly ILogger _log = Log.ForContext<ApiServerHttpHost>();
public static string RoutePrefix => "analysisapi";
/// <summary>
/// Base constructor requires a Name and Assembly where web service implementation is located
/// </summary>
public ApiServerHttpHost()
: base(typeof(ApiServerHttpHost).FullName, typeof(AnalysisServiceStackService).Assembly)
{
_log.Debug("ApiServerHttpHost constructed");
}
public override void SetConfig(HostConfig config)
{
base.SetConfig(config);
JsConfig.TreatEnumAsInteger = true;
JsConfig.EmitCamelCaseNames = true;
JsConfig.IncludeNullValues = true;
JsConfig.AlwaysUseUtc = true;
JsConfig<Guid>.SerializeFn = guid => guid.ToString();
JsConfig<Guid>.DeSerializeFn = Guid.Parse;
config.HandlerFactoryPath = RoutePrefix;
var exceptionMappings = new Dictionary<Type, int>
{
{typeof(JobServiceException), 400},
{typeof(NullReferenceException), 400},
};
config.MapExceptionToStatusCode = exceptionMappings;
_log.Debug("ApiServerHttpHost SetConfig ok");
}
/// <summary>
/// Application specific configuration
/// This method should initialize any IoC resources utilized by your web service classes.
/// </summary>
public override void Configure(Container container)
{
//Config examples
//this.Plugins.Add(new PostmanFeature());
//this.Plugins.Add(new CorsFeature());
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(AnalysisRunRequestValidator).Assembly);
.......
.......
.......
.......
container.Register<AnalysisPartValidator>(c => new AnalysisPartValidator(
c.Resolve<AnalysisDealPartLinkingModelEventSetValidator>(),
c.Resolve<AnalysisOutputSettingsPartValidMetaRisksValidator>(),
c.Resolve<AnalysisOutputSettingsGroupPartValidMetaRisksValidator>(),
c.Resolve<AnalysisDealPartCollectionValidator>(),
c.Resolve<AnalysisPortfolioPartCollectionValidator>(),
c.Resolve<UniqueCombinedOutputSettingsPropertiesValidator>()))
.ReusedWithin(ReuseScope.None);
container.Register<AnalysisRunRequestValidator>(c => new AnalysisRunRequestValidator(c.Resolve<AnalysisPartValidator>()))
.ReusedWithin(ReuseScope.None);
_log.Debug("ApiServerHttpHost Configure ok");
SetConfig(new HostConfig
{
DefaultContentType = MimeTypes.Json
});
}}
}
So I then hit this endpoint with this JSON
{
"Analysis": {
//Not important for discussion
//Not important for discussion
//Not important for discussion
//Not important for discussion
},
"CreatedBy": "frank"
}
And I get this response in PostMan tool (which I was expecting)
So that's all good.
.NET Core example
So now lets see what its like in .Net core example.
Lets start with the request dto
using System;
namespace ServiceStack.Demo.Model.Core
{
[Route("/analysis/run", "POST")]
public class AnalysisRunRequest : BaseRequest, IReturn<AnalysisRunResponse>
{
public AnalysisDto Analysis { get; set; }
}
}
Which uses this base request object
using System;
using System.Collections.Generic;
using System.Text;
namespace ServiceStack.Demo.Model.Core
{
public abstract class BaseRequest
{
public string CreatedBy { get; set; }
}
}
And here is the same validator we used from .NET 4.6.2 example, but in my .Net Core code instead
using System;
using System.Collections.Generic;
using System.Text;
using ServiceStack.Demo.Model.Core;
using ServiceStack.FluentValidation;
namespace ServiceStack.Demo.Core.Validators
{
public class AnalysisRunRequestValidator : AbstractValidator<AnalysisRunRequest>
{
public AnalysisRunRequestValidator(AnalysisDtoValidator analysisDtoValidator)
{
RuleFor(analysis => analysis.CreatedBy)
.Must(HaveGoodCreatedBy)
.WithMessage("CreatedBy MUST be 'sbarber'")
.WithErrorCode(ErrorCodes.ValidationErrorCode);
}
private bool HaveGoodCreatedBy(AnalysisRunRequest analysisRunRequest, string createdBy)
{
return createdBy == "sbarber";
}
}
}
And here is my host code for .Net core example
using System;
using System.Collections.Generic;
using System.Text;
using Funq;
using ServiceStack.Demo.Core.Api.Analysis;
using ServiceStack.Demo.Core.IOC;
using ServiceStack.Demo.Core.Services;
using ServiceStack.Demo.Core.Validators;
using ServiceStack.Text;
using ServiceStack.Validation;
namespace ServiceStack.Demo.Core.Api
{
public class ApiServerHttpHost : AppHostBase
{
public static string RoutePrefix => "analysisapi";
public ApiServerHttpHost()
: base(typeof(ApiServerHttpHost).FullName, typeof(AnalysisServiceStackService).GetAssembly())
{
Console.WriteLine("ApiServerHttpHost constructed");
}
public override void SetConfig(HostConfig config)
{
base.SetConfig(config);
JsConfig.TreatEnumAsInteger = true;
JsConfig.EmitCamelCaseNames = true;
JsConfig.IncludeNullValues = true;
JsConfig.AlwaysUseUtc = true;
JsConfig<Guid>.SerializeFn = guid => guid.ToString();
JsConfig<Guid>.DeSerializeFn = Guid.Parse;
config.HandlerFactoryPath = RoutePrefix;
var exceptionMappings = new Dictionary<Type, int>
{
{typeof(NullReferenceException), 400},
};
config.MapExceptionToStatusCode = exceptionMappings;
Console.WriteLine("ApiServerHttpHost SetConfig ok");
}
public override void Configure(Container container)
{
//Config examples
//this.Plugins.Add(new PostmanFeature());
//this.Plugins.Add(new CorsFeature());
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(ApiServerHttpHost).GetAssembly());
container.RegisterAutoWiredAs<DateProvider, IDateProvider>()
.ReusedWithin(ReuseScope.Container);
container.RegisterAutoWiredAs<FakeRepository, IFakeRepository>()
.ReusedWithin(ReuseScope.Container);
container.Register<LifetimeScopeManager>(cont => new LifetimeScopeManager(cont))
.ReusedWithin(ReuseScope.Hierarchy);
container.Register<DummySettingsPropertiesValidator>(c => new DummySettingsPropertiesValidator(c.Resolve<LifetimeScopeManager>()))
.ReusedWithin(ReuseScope.None);
container.Register<AnalysisDtoValidator>(c => new AnalysisDtoValidator(
c.Resolve<DummySettingsPropertiesValidator>()))
.ReusedWithin(ReuseScope.None);
container.Register<AnalysisRunRequestValidator>(c => new AnalysisRunRequestValidator(c.Resolve<AnalysisDtoValidator>()))
.ReusedWithin(ReuseScope.None);
SetConfig(new HostConfig
{
DefaultContentType = MimeTypes.Json
});
}
}
}
And this is me trying to now hit the .Net Core endpoint with the same bad JSON payload as demonstrated above with the .Net 4.6.2 example, which gave correct Http response (i.e included error that I was expecting in response)
Anyway here is payload being sent to .Net Core endpoint
{
"Analysis": {
//Not important for discussion
//Not important for discussion
//Not important for discussion
//Not important for discussion
},
"CreatedBy": "frank"
}
Where we can see that we are getting into the .Net Core example validator code just fine
But this time I get a very different Http response (one that I was not expecting at all). I get this
It can be seen that we do indeed get the correct Status code of "400" (failed) which is good. But we DO NOT get anything about the validation failure at all.
I was expecting this to give me the same http response as the original .Net 4.6.2 example above.
But what I seem to be getting back is the JSON representing the AnalysisRunResponse. Which looks like this
using System;
using System.Collections.Generic;
using System.Text;
namespace ServiceStack.Demo.Model.Core
{
public class AnalysisRunResponse : BaseResponse
{
public Guid AnalysisUid { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace ServiceStack.Demo.Model.Core
{
public abstract class BaseResponse
{
public ResponseStatus ResponseStatus { get; set; }
}
}
I thought the way ServiceStack works (in fact that is how it works for ALL our existing .Net 4.6.2 code) is that the validation is done first, if AND ONLY if it passes validation is the actual route code run
But this .Net core example seems to not work like that.
I have a break point set in Visual Studio for the actual route and Console.WriteLine(..) but that is never hit and I never see the result of the Console.WriteLine(..)
What am I doing wrong?
This doesn't seem to any longer an issue with the latest v5 of ServiceStack that's now available on MyGet.
As sending this request:
Is returning the expected response:
The .NET Core packages are merged with the main packages in ServiceStack v5 so you'll need to remove the .Core prefix to download them, i.e:
<PackageReference Include="ServiceStack" Version="5.*" />
<PackageReference Include="ServiceStack.Server" Version="5.*" />
You'll also need to add ServiceStack's MyGet feed to fetch the latest ServiceStack v5 NuGet packages which you can do by adding this NuGet.config in the same folder as your .sln:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="ServiceStack MyGet feed" value="https://www.myget.org/F/servicestack" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
The code provided in the book Pro ASP.NET MVC 5 from Apress in chapter 16 (Routing Incoming URLs) The example is about legacy urls. Next i will put the code samples for the custom route, routeconfig, controller and view.
LegacyRoute.cs
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace UrlsAndRoutes.Infrastructure
{
public class LegacyRoute : RouteBase
{
private string[] urls;
public LegacyRoute(params string[] targetUrls)
{
urls = targetUrls;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase))
{
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action", "GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
VirtualPathData result = null;
if (values.ContainsKey("legacyURL") && urls.Contains((string)values["legacyURL"], StringComparer.OrdinalIgnoreCase))
{
result = new VirtualPathData(this, new UrlHelper(requestContext).Content((string)values["legacyURL"]).Substring(1));
}
return result;
}
}
}
RouteConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Mvc.Routing.Constraints;
using UrlsAndRoutes.Infrastructure;
namespace UrlsAndRoutes
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
//routes.MapRoute("NewRoute", "App/Do{action}", new { controller = "Home", id = UrlParameter.Optional });
//routes.Add(new Route("SayHello", new CustomRouteHandler()));
routes.Add(new LegacyRoute("~/articles/Windows_3.1_Overview.html", "~/old/.NET_1.0_Class_Library"));
routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
routes.MapRoute("MyOtherRoute", "App/{action}", new { controller = "Home" });
}
}
}
LegacyController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace UrlsAndRoutes.Controllers
{
public class LegacyController : Controller
{
public ActionResult GetLegacyURL(string legacyURL)
{
return View((object)legacyURL);
}
}
}
GetLegacyURL.cshtml
#model string
#{
ViewBag.Title = "GetLegacyURL";
Layout = null;
}
<h2>GetLegacyURL</h2>
The URL requested was: #Model
I can't figure how to put it work. I always get 404 error (http://my.machine/articles/Windows_3.1_Overview.html). The method in the GetRouteData in LegacyRoute.cs is never called. If I remove the . from the URL the code works fine. Can anyone give some advice or help?
It is strange that no one are complaining that the code doesn't work.
Page 445 provides the solution. You need to edit IIS Express settings.
Right click on the IIS Express icon on the taskbar while the application is running -> Show all applications -> Click on the site you want to configure -> Click on the configuration file
Search for System.Web.Routing.UrlRoutingModule
Remove the preCondition attribute value so the line becomes <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
Restart the application and you are ready.
routes.MapMvcAttributeRoutes();
routes.Add(new LegacyRoute("~/articles/Windows_3.1_Overview.html/",
"~/old/.NET_1.0_Class_Library/"));
routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home" ,action="index" });
routes.MapRoute("MyOtherRoute", "App/{action}", new { controller = "Home" });
Try with above code , this should be worked.
Malinda Sanjaka
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace abc
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
EmoticonRender ab = new EmoticonRender();
private void button1_Click(object sender, EventArgs e)
{
string textie = ab.Parse(textBox1.Text);
richTextBox1.Text += textie+"\n";
}
}
public class EmoticonRender
{
private List<KeyValuePair<string, string>> _dictionary = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>(":-)", "a.png"),
new KeyValuePair<string, string>(";-(", "a.png"),
};
public string Parse(string text)
{
foreach(KeyValuePair<string, string> kvp in _dictionary)
{
text = text.Replace(kvp.Key, #"C:\Users\Buddiez\Documents\Visual Studio 2010\Projects\abc\abc\a.png");
}
return text;
}
}
}
im using these line of codes to insert smilyes into richtextbox but instead of showing smileye it is showing the path of the png imgae ie. C:\Users\Buddiez\Documents\Visual Studio 2010\Projects\abc\abc\a.png
Copy all the images which you have and navigate to >> visual studio select Project>>Properties.There select Resources and paste all copied images on the right side pane.
Hashtable emotions;
void CreateEmotions()
{
emotions= new Hashtable(6);
emotions.Add(":-)", Project.Properties.Resources.regular_smile);
emotions.Add(":)", Project.Properties.Resources.regular_smile);
}
void AddEmotions()
{
foreach (string emote in emotions.Keys)
{
while(richTextBox1.Text.Contains(emote))
{
int ind = richTextBox1.Text.IndexOf(emote);
richTextBox1.Select(ind, emote.Length);
Clipboard.SetImage((Image)emotions[emote]);
richTextBox1.Paste();
}
}
}
A good (and relatively new) solution could be using the open-source EmojiBox project.
There's not much code there so it's quite easy to follow, just note that in order to insert an emoji into the custom RichTextBox there, the text you type has to follow the template of :emoji_name:
Of course, if you don't want to use the whole list of unicode emojis, you could also replace the image files or their names/descriptions within the json file.
I'm experimenting with the documentation of http://www.restfulrouting.com/. When I open my routedug the links are like i want. But when I click the link i get a 404. I have the following structure
1. Login
1.1 Company (Area)
1.1.1 Departments
1.1.2 Contacts
1.1.1 Company info
1.2 Customer (Area)
//other information
My folder structure
Controllers (folder)
customers (folder)
AreasController.cs
CompanyController.cs
TestController.cs
AccountController.cs
Routes.cs
using System.Web.Routing;
using RestfulRouting;
using extranet.Controllers;
using extranet.Controllers.customers;
[assembly: WebActivator.PreApplicationStartMethod(typeof(extranet.Routes), "Start")]
namespace extranet
{
public class Routes : RouteSet
{
public override void Map(IMapper map)
{
map.DebugRoute("routedebug");
map.Resource<CompanyController>(comp => comp.Only("show"));
/*******************************
********COMPANYAREA*************
********************************/
map.Area<AreasController>("customer", area =>
{
area.Resource<TestController>();
area.Resource<CompanyController>();
});
}
public static void Start()
{
var routes = RouteTable.Routes;
routes.MapRoutes<Routes>();
}
}
}
CompanyController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Web;
using System.Web.Mvc;
namespace extranet.Controllers
{
public class CompanyController : ApplicationController
{
//
// GET: /Company/
public ActionResult Index()
{
return View();
}
public ActionResult Show()
{
return View();
}
}
}
My question is when I go to {mysite}/customer/company --> I get the 404 page. When i got to {mysite}/company it shows me the page. What am I overseeing or where is my mistake? If I am missing some code here please tell me then I will place an edit.
Thanks in advance
Wow, just spend 4 hours figuring it out. Turns out i dragged the CompanyController from my controllers map to my customers class. Which means the namespace wasn't changed --> means link didn't recognize the controller.
I just had to add: namespace extranet.Controllers.Customers
Is it possible to make a String in a web part properties editable with a rich text box (to be able to use the Bold, etc.) ?
UPDATE / SOLUTION
The 1st class is the "Custom property" that should appear in the toolbar
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
namespace MyCustomProperty
{
public class RichTextToolbarProperty : Microsoft.SharePoint.WebPartPages.ToolPart
{
InputFormTextBox textBox;
Panel toolPartPanel;
protected override void CreateChildControls()
{
toolPartPanel = new Panel();
toolPartPanel.GroupingText = "Default text here";
textBox = new InputFormTextBox();
textBox.TextMode = TextBoxMode.MultiLine;
textBox.Rows = 10;
textBox.RichText = true;
textBox.RichTextMode = SPRichTextMode.FullHtml;
BasePublicationWebPart wp = (BasePublicationWebPart)this.ParentToolPane.SelectedWebPart;
textBox.Text = wp.DefaultText;
toolPartPanel.Controls.Add(textBox);
Controls.Add(toolPartPanel);
base.CreateChildControls();
}
public override void ApplyChanges()
{
BasePublicationWebPart wp = (BasePublicationWebPart)this.ParentToolPane.SelectedWebPart;
wp.DefaultText = textBox.Text;
}
}
}
The 2nd class is the WebPart :
using System;
using System.Data;
using System.Text;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
namespace MyWebPart
{
public abstract class BasePublicationWebPart : Microsoft.SharePoint.WebPartPages.WebPart
{
public string DefaultText
{
get
{
return _defaultText;
}
set { _defaultText = value; }
}
public override ToolPart[] GetToolParts()
{
ToolPart[] allToolParts = new ToolPart[3];
WebPartToolPart standardToolParts = new WebPartToolPart();
CustomPropertyToolPart customToolParts = new CustomPropertyToolPart();
allToolParts[0] = standardToolParts;
allToolParts[1] = customToolParts;
allToolParts[2] = new MyCustomProperty.RichTextToolbarProperty();
return allToolParts;
}
// ... some usual web part code should go here ... ///
Yes it is, you might want to inspect, how the "Custom Content Editor Web Part" is built: http://www.codeproject.com/KB/sharepoint/Custom_CEWP_4_SharePoint.aspx