I'm working on a form which will allow a local businesses to register their contact data on our site.
I'm using a SurfaceController and I'm saving the data using an IContentService. This works just fine for simple text properties. But I also allow them to inform their website. The document type has a URL Picker for the Website and it poses some problems.
First here is the code:
private void SaveRegisterBusinessRequestToUmbraco(RegisterBusinessViewModel business)
{
//do some other stuff
var title = business.BusinessName + " (" + DateTime.Now.ToUniversalTime().ToString("yyyy-MM-dd HH:mm") + ")";
var newNode = _contentService.Create(title, listRootNode.Id, BusinessContactCard.ModelTypeAlias);
newNode.SetValue(BusinessContactCard.GetModelPropertyType(x => x.BusinessName).Alias, business.BusinessName);
newNode.SetValue(BusinessContactCard.GetModelPropertyType(x => x.PhoneNumber).Alias, business.PhoneNumber);
newNode.SetValue(BusinessContactCard.GetModelPropertyType(x => x.MobilePhoneNumber).Alias, business.MobilePhoneNumber);
newNode.SetValue(BusinessContactCard.GetModelPropertyType(x => x.FaxNumber).Alias, business.Fax);
newNode.SetValue(BusinessContactCard.GetModelPropertyType(x => x.Website).Alias, business.Website);
if (_contentService.Save(newNode).Success)
{
//do some stuff
}
}
I have an exception when business.Website is not empty on the _contentService.Save line:
Unexpected character encountered while parsing value: w. Path '', line
0, position 0
Here is the stack trace:
[JsonReaderException: Unexpected character encountered while parsing value: w. Path '', line 0, position 0.]
Newtonsoft.Json.JsonTextReader.ParseValue() in /_/Src/Newtonsoft.Json/JsonTextReader.cs:1706
Newtonsoft.Json.JsonTextReader.Read() in /_/Src/Newtonsoft.Json/JsonTextReader.cs:419
Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter) in /_/Src/Newtonsoft.Json/JsonReader.cs:1195
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:196
Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in /_/Src/Newtonsoft.Json/JsonSerializer.cs:907
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in /_/Src/Newtonsoft.Json/JsonConvert.cs:828
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, JsonSerializerSettings settings) in /_/Src/Newtonsoft.Json/JsonConvert.cs:786
Umbraco.Web.PropertyEditors.<GetReferences>d__7.MoveNext() in d:\a\1\s\src\Umbraco.Web\PropertyEditors\MultiUrlPickerValueEditor.cs:182
Umbraco.Core.PropertyEditors.DataValueReferenceFactoryCollection.GetAllReferences(PropertyCollection properties, PropertyEditorCollection propertyEditors) in d:\a\1\s\src\Umbraco.Core\PropertyEditors\DataValueReferenceFactoryCollection.cs:33
Umbraco.Core.Persistence.Repositories.Implement.ContentRepositoryBase`3.PersistRelations(TEntity entity) in d:\a\1\s\src\Umbraco.Core\Persistence\Repositories\Implement\ContentRepositoryBase.cs:829
Umbraco.Core.Persistence.Repositories.Implement.DocumentRepository.PersistNewItem(IContent entity) in d:\a\1\s\src\Umbraco.Core\Persistence\Repositories\Implement\DocumentRepository.cs:503
Umbraco.Core.Cache.DefaultRepositoryCachePolicy`2.Create(TEntity entity, Action`1 persistNew) in d:\a\1\s\src\Umbraco.Core\Cache\DefaultRepositoryCachePolicy.cs:96
Umbraco.Core.Persistence.Repositories.Implement.RepositoryBase`2.Save(TEntity entity) in d:\a\1\s\src\Umbraco.Core\Persistence\Repositories\Implement\RepositoryBaseOfTIdTEntity.cs:138
Umbraco.Core.Services.Implement.ContentService.Save(IContent content, Int32 userId, Boolean raiseEvents) in d:\a\1\s\src\Umbraco.Core\Services\Implement\ContentService.cs:791
WeiswampachCms.Controllers.RegisterBusinessController.SaveRegisterBusinessRequestToUmbraco(RegisterBusinessViewModel business) in C:\Users\ragi\OneDrive\Development\WeiswampachCms-Umbraco8\WeiswampachCms-Umbraco8\Controllers\RegisterBusinessController.cs:94
WeiswampachCms.Controllers.RegisterBusinessController.ContactFormSubmit(RegisterBusinessViewModel businessViewModel) in C:\Users\ragi\OneDrive\Development\WeiswampachCms-Umbraco8\WeiswampachCms-Umbraco8\Controllers\RegisterBusinessController.cs:59
lambda_method(Closure , ControllerBase , Object[] ) +103
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.Async.<>c.<BeginInvokeSynchronousActionMethod>b__9_0(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
System.Web.Mvc.Async.<>c__DisplayClass11_0.<InvokeActionMethodFilterAsynchronouslyRecursive>b__0() +58
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass7_0.<BeginInvokeActionMethodWithFilters>b__1(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
System.Web.Mvc.Async.<>c__DisplayClass3_6.<BeginInvokeAction>b__4() +35
System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__1(IAsyncResult asyncResult) +100
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
System.Web.Mvc.<>c.<BeginExecuteCore>b__152_1(IAsyncResult asyncResult, ExecuteCoreState innerState) +11
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +45
System.Web.Mvc.<>c.<BeginExecute>b__151_2(IAsyncResult asyncResult, Controller controller) +13
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.<>c.<BeginProcessRequest>b__20_1(IAsyncResult asyncResult, ProcessRequestState innerState) +28
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +576
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +132
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163
I guess is it is because the value of an URL picker is saved in the DB in a JSON format, but what is the structure? Is there a simple way of doing this?
Here's a proof of concept that's loosely typed, can definitely be done better using the strongly typed models, but works.
It's setting up JArray then the url picker object. I'm assuming you've used the Multi Url Picker??
My test code just uses the homenode but hopefully you can see what I'm doing.
Few things to note:
Check the user enters a valid url? Append the protocol?
You almost probably certainly shouldn't be storing web form entries to
your content tree. You're opening up yourself to security issues or at
the very least denial of service / spam issues. A custom table would be a much better solution here (probably) .
But hope this is useful.
var _contentService = Services.ContentService;
var homeCsNode = _contentService.GetById(1106);
// test getting the urlpicker content (useful to see what Umbraco set)
var testJson = homeCsNode.GetValue<string>("urlPicker");
var urlPickerNewValueList = new JArray(); // a list of url picker items
var urlPickerNewValueObj = new JObject(); // the first (and only) item
urlPickerNewValueObj.Add("name", "http://www.yahoo.co.uk"); // we add the name and url as the same value as that is what Umbraco seems to do
urlPickerNewValueObj.Add("url", "http://www.yahoo.co.uk"); // you might need to check for the protocol and add it if omittted?
urlPickerNewValueList.Add(urlPickerNewValueObj);
// set the value in the Content Service
homeCsNode.SetValue("urlPicker", JsonConvert.SerializeObject(urlPickerNewValueList));
_contentService.SaveAndPublish(homeCsNode);
Thanks for your answer. I actually figured it out myself shortly after posting. I did pretty much the same as you did. Just had to check in to Umbraco DB how Multi URL Picker Data is saved. After that it was a piece of cake :-)
Save URL using IContentServer
Hello,
I'm working on a form which will allow a local businesses to register their contact data on our site.
I'm using a SurfaceController and I'm saving the data using an IContentService. This works just fine for simple text properties. But I also allow them to inform their website. The document type has a URL Picker for the Website and it poses some problems.
First here is the code:
I have an exception when business.Website is not empty on the _contentService.Save line:
Here is the stack trace:
I guess is it is because the value of an URL picker is saved in the DB in a JSON format, but what is the structure? Is there a simple way of doing this?
Thanks
Hi,
Here's a proof of concept that's loosely typed, can definitely be done better using the strongly typed models, but works.
It's setting up JArray then the url picker object. I'm assuming you've used the Multi Url Picker??
My test code just uses the homenode but hopefully you can see what I'm doing.
Few things to note:
But hope this is useful.
Hi Steve,
Thanks for your answer. I actually figured it out myself shortly after posting. I did pretty much the same as you did. Just had to check in to Umbraco DB how Multi URL Picker Data is saved. After that it was a piece of cake :-)
Regards
is working on a reply...