Произошла ошибка на этапе развертывания "Retract Solution": <CLASS> не может быть десериализован, поскольку у него нет общедоступного конструктора по умолчанию
Я использую этот учебник в качестве примера для создания задания таймера.
Вот мой код работы таймера:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
namespace CalcAnnualConsumptionTotals
{
public class GroupAnnualConsumption : SPJobDefinition
{
public GroupAnnualConsumption() : base() {} // <-- public default constructor
public GroupAnnualConsumption(string jobName, SPService service,
SPServer server, SPJobLockType lockType)
: base(jobName, service, server, lockType)
{
this.Title = "Group Annual Consumption";
}
public GroupAnnualConsumption(string jobName, SPWebApplication webapp)
: base(jobName, webapp, null, SPJobLockType.ContentDatabase)
{
this.Title = "Group Annual Consumption";
}
public override void Execute(Guid targetInstanceId)
{
.....
}
}
}
Как вы можете видеть, у меня есть открытый конструктор по умолчанию, но когда я пытаюсь развернуть его, он показывает мне ошибку:
Произошла ошибка на этапе развертывания "Решение отвода": CalcAnnualConsumpTotals.GroupAnnualConsump не может быть десериализован, поскольку у него нет общедоступного конструктора по умолчанию
Когда я впервые получил эту ошибку, я на самом деле забыл добавить конструктор по умолчанию. Но даже после добавления это показывает мне ошибку. Я думал, что моя первоначальная попытка будет частично успешной, что приведет к развертыванию. Но я не могу найти его даже через центральную администрацию или Get-SPTimerJob
,
Любые идеи, почему эта ошибка появляется.
4 ответа
Хорошо, здесь была проблема. Как я уже упоминал в вопросе
... Когда я впервые получил эту ошибку, я на самом деле забыл добавить конструктор по умолчанию....
Так что случилось то, что решение было развернуто на SharePoint, но ошибка появилась и в первый раз (не могу вспомнить, была ли это та же ошибка или нет). В следующий раз, когда я исправил ошибку и попытался развернуть ее, она показала мне ошибку:
Произошла ошибка на этапе развертывания "Решение отвода": CalcAnnualConsumpTotals.GroupAnnualConsump не может быть десериализован, поскольку у него нет общедоступного конструктора по умолчанию
Решение Retract было ключевым словом здесь. Когда SharePoint пытался развернуть обновленное решение, ему пришлось отказаться от старого, но не смог, и из-за ошибки в (старом) решении.
Поэтому я пошел в Управление решениями фермы в центре администрирования и удалил решение. Затем, когда я развернул, это сработало.
Вышесказанное не сработало для меня, но я нашел решение и хотел опубликовать его здесь на случай, если кто-то столкнется с такой же ситуацией.
В моем случае мне не удалось удалить через страницу "Управление решениями для фермы", по крайней мере, изначально.
Я должен был сначала исправить код, добавив конструктор по умолчанию. Затем мне пришлось GAC файл с помощью gacutil. Затем я сбрасываю IIS с помощью iisreset / restart. Только тогда я смог запросить отзыв решения на странице "Управление решениями для фермы".
К сожалению, тогда он просто сидел там. Итак, чтобы решить эту проблему, я сделал:
- stsadm -o enumdeployments
- stsadm -o canceldeployment -id "значение guid, отображаемое на шаге 1"
- через powershell: remove-spsolution -Identity solutionname.wsp -force
- iisreset / restart (вы можете получить ошибку при повторном развертывании, что решение все еще установлено, если вы не сбросили iis вручную)
Тогда я смог перераспределить и вернуться к работе.
Похоже, что "старая версия" SharePoint Job все еще работает.
При развертывании задания SharePoint служба таймера SharePoint должна быть перезапущена.
Как перезапустить службу таймера SharePoint через PowerShell
function Restart-SPTimerV4()
{
[array]$servers= Get-SPServer | ? {$_.Role -eq "Application"}
$farm = Get-SPFarm
foreach ($server in $servers)
{
Write-Host "Restarting Timer Job on $server"
$Service = Get-WmiObject -Computer $server.name Win32_Service -Filter "Name='SPTimerV4'"
if ($Service -ne $null)
{
$Service.InvokeMethod('StopService',$null)
Start-Sleep -s 7
$service.InvokeMethod('StartService',$null)
Start-Sleep -s 7
Write-Host "Timer Job successfully restarted on $server"
}
else
{
write-host -ForegroundColor Yellow "Could not find SharePoint 2010 Timer Service on $server"
}
}
}
Вам также необходимо вызвать либо конструктор ассоциации веб-службы, либо конструктор ассоциации приложения-службы из одного из конструкторов определения задания таймера. Помните, что ваше задание таймера должно быть связано с одним из этих двух объектов. Единственное время, когда можно создать ассоциацию, - это конструкторы класса SPJobDefinition, поэтому один из ваших конструкторов должен быть связан с вызовом соответствующего базового конструктора.
Похоже, вам нужно установить одно из этих двух свойств из вашего конструктора по умолчанию. Было бы проще, если бы вы могли передать значения одному из ваших других конструкторов.
Изменить: чтобы уточнить, я думаю, передавая jobname
Параметр для базового конструктора будет достаточно. Если у вас нет доступа к этому значению (это жестко запрограммировано или в файле конфигурации?), Возможно, вам придется изменить структуру.
Тем не менее, я никогда не работал с Sharepoint, поэтому я могу быть вне базы.